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

Dynamically rendered components not updating within <Element>

Open ITCuw opened this issue 2 years ago • 3 comments

Been using craft.js for months now, it's fantastic 🏆

Describe the bug I have a card component in which I want the contents to be draggable within the card itself. Users can add components to this card by clicking a button that adds data to the cardData JSON (See example code below). The issue is that whenever I update the JSON data, the updates don't show up on the page. To be clear, this component is rendered within a parent instance of Element just like in the example craft js gives with the card component rendered within the parent Element component.

Expected behavior I expect that whenever the JSON data is updated, the updates are rendered on the page. The code works when I remove the Element component.

Example code <Element id="text" is='div' canvas> {cardData?.map((page, key) => { return ( <StyledItem key={key} pageName={page.name} /> ) })} </Element>

Additional context Add any other context about the problem here.

Your environment

Software
craft.js
Next.js
npm

ITCuw avatar Nov 23 '21 23:11 ITCuw

Hi @ITCuw,

This is an expected behaviour for now. When you do this:

const YourComponent = () => {
  return (
     <div>
       <Element id="text" is="div">
          ...
      </Element>
   </div>
  )

Essentially, that's creating a new Linked Node of type div and is linked to the parent YourComponent node. The values that you specify in that <Element /> are used as the default values when creating the Linked Node. Once it has been created, the values in the Craft's State is used as the single source of truth. In other words, even if you were to do an update via React to the <Element />, these changes will not be propagated to the Craft state.

The only way to change the values in the linked Node is via Craft's APIs:

const YourComponent = () => { 
  const { id } = useNode();
  const { actions, query } =useEditor();
 
  useEffect(() => {
      const linkedNodeId = query.node(id).get().data.linkedNodes['text']; // "text" is the "id" that you specify in <Element />
      actions.setProp(linkedNodeId, props => {
         // do something
      });
   }, []);

  return (
     <div>
       <Element id="text" is="div">
          ...
      </Element>
   </div>
  )
}

prevwong avatar Dec 13 '21 13:12 prevwong

@prevwong Using setProp this way, and updating props.children, doesn't work. any other props than children works correctly.

shreyas-jadhav avatar May 29 '23 07:05 shreyas-jadhav

I'm getting the same problem on this. Does anyone have any updates? How to programmatically add elements to specific Element as children? Please?

nephew92 avatar Feb 08 '24 17:02 nephew92