craft.js
craft.js copied to clipboard
Updating value in parent component child component value doesn't change
Hey @prevwong I have a parent component which consists of text box for changing value. And my all child component is draggable so they are in <Editor> tag while I change the value of text box parent state value is updated but my child props not update even in the useEffect method it will not catch the value.
Parent Component
Child Component
Video
Here is a video presentation for better understanding while change the text into text box the value in right side is not changing although in the child component we have console log as you can see in the bottom in console bar no log is encounter while changing the value.
Hi @skychavda
This is an expected behaviour. The <Element />
is intended to define a Node for a given React Element. From that point on, the React Element is governed by its corresponding Node.
So in your example:
<Element id="header" is={HeaderMovable}>
<Text />
<Text />
<Text />
</Element>
The Element component creates a Node for the underlying Header
component, and a Node for each child <Text />
component. These elements are then controlled by their corresponding Node, therefore you can't manually mutate their props as you would in React, you will need to mutate their Nodes instead.
In your case, you should either let all the editing be done via the PersonalDetails
component - in which case, you shouldn't need to create a Linked Node for your header element. Or let the Text
component be editable independently.
Thanks @prevwong.
I am changing the value of which is in the h1
tag.
These elements are then controlled by their corresponding Node, therefore you can't manually mutate their props as you would in React, you will need to mutate their Nodes instead.
Please elaborate more on this cause I didn't understand your point.
Given this component:
const Button = () => {
return (
<div>
<Element id="text" is={Text} text="Some default text" />
</div>
)
)
You cannot manually change the props via React:
const Button = ({textValue}) => {
return (
<div>
<Element id="text" is={Text} text={textValue} /> ❌ // even if textValue changes, nothing will happen
</div>
)
)
Instead, can only change the props of the Text
component via its Node:
const Button = ({textValue}) => {
const { actions: { setProp } } = useEditor();
const { textNodeId } = useNode(node => ({
textNodeId: node.data.linkedNodes.text
});
useEffect(() => {
if ( !textNodeId ) {
return;
}
setProp(textNodeId, props => props.text = "Changed value");
}, [textValue, textNodeId]);
return (
<div>
<Element id="text" is={Text} text="Some default text" />
</div>
)
)
This is not a good pattern to follow in most cases. Each Node is supposed to be editable by the user and therefore shouldn't have to to rely on props propagating from any parent component.