1

In React we are loading a list of children components that define their own ID. We want to then do a pass where we re-arrange the children based on their set internal ID. How do we communicate the internal ID to the parent? Also it would be nice to use that ID as the parent rendering ekey. Note the internal ID does not match the component name.

class Thing1 extends React.Component {
   const ID = 'Thing1IDString';
}

class Thing2 extends React.Component {
   const ID = 'Thing2IDString';
}


<Parent>
 <Thing1 />
 <Thing2 />
 <Thing3 />
</Parent>
Kenoyer130
  • 6,874
  • 9
  • 51
  • 73

3 Answers3

3

The first thing I'd suggest is trying to make the parent know how to compute the child IDs somehow. If the child IDs come from a database, then make the parent compute them instead of making the children compute them. The lower components in the tree should be less intelligent. Hand them everything they need to know in its final form, so they can simply render it.

The structure you're talking about, where the child has "private" data that the parent needs to act upon, is generally solved in React by:

  • Storing that data in the parent
  • Passing the data to the child as a prop
  • Passing an onDataChanged function to the child, so that the child can tell the parent when the data changes.

This is the "controlled input" pattern. It feels awkward at first, and may seem like there's too much indirection at first glance. But the advantage is that the data flow is very predictable.

Now, if that isn't possible in your case, and you really need the children to "register" with the parent, then you can use props or context to pass a registerChild function to the children. In the child, use its componentDidMount lifecycle method to call the registerChild function with its computed ID. The parent can then keep track of these IDs however it needs to.

Dave Ceddia
  • 1,480
  • 2
  • 17
  • 24
  • So our case is the second. The parent hosts 4 -5 "Form" components but the layout is determined by the database. The user can drag and drop them around and the parent has 10-20 that might be displayed per page. Basically imagine a large scale app with 100's of screens that can be re-arranged by the user. So we can't just include a list of components for the parent to choose from. Thanks! – Kenoyer130 Mar 04 '17 at 13:31
  • Also you mentioned context but the official documentation seems to discourage that. (https://facebook.github.io/react/docs/context.html) – Kenoyer130 Mar 04 '17 at 13:32
  • Props is the preferred way to pass down data and callbacks - context is usually used for more "advanced" things like form libraries or other cases where the parent and child need tight coupling without making the user responsible for setting it up. – Dave Ceddia Mar 04 '17 at 19:08
  • Based on your use case, I think you could do it by having the parent load the data, child ids, and positions, then pass that down to the children in props. Also pass down a callback which the children can call when they need to reorder themselves, and the parent would accumulate that info and send it up to the server. Basically, putting as much logic in the parent as possible. – Dave Ceddia Mar 04 '17 at 19:11
1

Your syntax is kind of confusing. Let's convert the pseudo-example to an actual working ReactJS code sample.

Let's say you have a child(s) component(s):

class Thing1 extends React.Component {
    constructor(props) {
        super(props);

        this.id = 'Thing1IDString';
    }

    render(){
        return (
            <p>Child component</p>
        );
    }
}

If you want to access Thing1's id property from your parent component, there are several ways how to do communicate between components.

It depends what you want to achieve. If you just want to access a child component property, you may use refs:

class Parent extends React.Component {
    doSomething() {
        // Access anything you need from `this.refs.thing1`
        const thing1ID = this.refs.thing1.id;
    }
    render() {
        return (
            <div>
                <button onClick={this.doSomething.bind(this)}>Get ID</button>
                <Thing1 ref="thing1" />       
            </p>
        );
    }
}
Community
  • 1
  • 1
Kaloyan Kosev
  • 12,483
  • 8
  • 59
  • 90
0

I've touched above problem here: https://github.com/facebook/react/issues/15320

There are 3 methods you can use to achieve Parent child data transfer (context Api, mutatiin, Reac.Children deep traversal).

Patryk Janik
  • 2,476
  • 2
  • 13
  • 23