craft.js icon indicating copy to clipboard operation
craft.js copied to clipboard

Updating value in parent component child component value doesn't change

Open skychavda opened this issue 3 years ago • 5 comments

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 image

Child Component image

skychavda avatar May 22 '21 08:05 skychavda

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.

video

skychavda avatar May 22 '21 08:05 skychavda

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.

prevwong avatar May 22 '21 09:05 prevwong

Thanks @prevwong. I am changing the value of which is in the h1 tag.

skychavda avatar May 22 '21 09:05 skychavda

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.

skychavda avatar May 22 '21 09:05 skychavda

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.

prevwong avatar May 22 '21 13:05 prevwong