I have a parent component that holds a string as a state. This string is composed with help from other child components.
Then the parent sends this string to a DisplayText component that displays it. However in the DisplayText component there is an internal state for that string and thus the user can change it however they like, and the result
const [myString, setMyString] = React.useState<string>('');
React.useEffect(() => {
// do some stuff with the string and save it
setMyString(string);
}, [...]);
<Textarea
value={myString}
onChange={(value) => setMyString(value)}
/>
(This is just basic React.) I would like to add a button in the parent component that forces the child to override any changes the user has made, and re-render the text coming from the parent. This happens naturally when the state in the parent changes, but how can you simulate the same effect when a button in the parent is clicked?
I could solve this by moving the internal state of editing the text from the child to the parent, so clicking the button can control that, but is there another way without doing so? Because the edited text shouldn't concern the parent. The second solution I thought of would be to force a re-render of the parent but the ways to do so are hacky (changing a dummy state). Is there a simple solution to this?
CodePudding user response:
That sounds like bad practice to me.
You should:
- lift state up to parent and have a default value which is saved. Clicking the button should just reset to the default value.
- If you need to change the parent state from one or more childs, you should pass down a setter function which sets the state in the parent.
CodePudding user response:
Composing a string in multiple child components seems like a bad approach to me. But if you really need or want to do it that way, then adding a button in the partent component, that overwrites myString
, should work. The props that refer to this value will update automatically. Just remove the internal state of the children, to have a 'single source of truth'.