In react I can do something like:
App.jsx
const App = () => {
const [state, setState] = useState("old value")
return (
<>
<ChildComponent setState={setState} />
</>
)
}
ChildComponent.jsx
const ChildComponent = ({ setState }) => {
const changeState = () => setState("new value")
return (
<div>
<button onClick={changeState}>Click</button>
</div>
)
}
Then the parent state will be updated.
I don't know how to do the same in Svelte...
I have this:
index.svelte
<script>
import { ChildComponent } from "@components"
let state = "old value"
</script>
<main>
<ChildComponent {state} />
</main>
ChildComponent.svelte
<script>
export let state
const changeState = () => {
// I need to do something like:
state = "new value"
}
</script>
<div>
<button on:click={changeState}>Click</button>
</div>
And see the new value reflected in the parent.
I wanna to do it without use stores... I don't know if it's possible.
Maybe store is the only way to proceed.
I'm ears
There are two ways of doing this in Svelte:
With two-way binding
This will create a sort of connection between parent and child, where updating one will automatically update the other.
<!-- Parent.svelte -->
<script>
import Child from './Child.svelte';
let state = "initial";
</script>
<Child bind:state />
<!-- Child.svelte -->
<script>
export let state;
function changeState() {
state = "new value";
</script>
<button on:click={changeState}>Click</button>
Using events
Just like props go down, events are used to pass informaton up. This can be used if you don't want a strict equivalence between the two states and is a touch more versatile (but also more verbose).
<!-- Parent.svelte -->
<script>
import Child from './Child.svelte';
let state = "initial"
function handleChange(ev) {
state = ev.detail.state
}
</script>
<Child {state} on:change={handleChange} />
<!-- Child.svelte -->
<script>
import { createEventDispatcher } from 'svelte';
export let state
const dispatch = createEventDispatcher()
function changeState() {
// first argument is the event name
// second is an object placed in ev.detail
dispatch('change', { state: "new value" });
}
</script>
<button on:click={changeState}>Click</button>
Which of these to use is up to you and likely depends on the situation, but both benefit that they do not actively rely on what is happening outside the component. If nobody used bind the component doesn't care, it still works. If nobody is listening to this event, again the component doesn't care and keeps on working. Contrast this to the situation where no function is passed, or the function has the wrong signature, suddenly your component is dependent on something that it cannot control which is not a good pattern.