3

I want to make my child components have a ref, but I don't want the user to have to specify the ref when they create the component. So say I have something like this:

<Parent>
    <Child />
    <Child />
</Parent>

And I want the parent to be able to access the Child components' state. The easy way is to add a ref to each component, but I would like this to the be something that is done during the constructor() function to abstract this away from the end user, as I'd like these components to be generalized.

Is there a clean way to make it so the parent can access the state of the child components, such as when the Child is created you have something like:

class Child extends Component {
    constructor(){
        super();
        this.state = {'abc': 123}
        this.ref=Math.random();
    }
}

So that inside of the Parent class I can do something like:

 class Parent extends Component {
     componentWillMount(){
         console.log(this.refs);
     }
 }

So I want to be able to declare a set of components like:

class App extends Component {
    render(){
       <Parent> <Child /> <Child /> </Parent>
    }
}

So that I can access each child and it's state as the parent iterates through child components.

4
  • You can not access child component state from parent. State can be accessed, modified from it own class. Commented Mar 4, 2017 at 21:19
  • you actually can with a ref Commented Mar 4, 2017 at 21:29
  • I mean setting state of child component state from parent. You cant do this Commented Mar 4, 2017 at 21:33
  • check this. stackoverflow.com/questions/27864951/… Commented Mar 4, 2017 at 21:48

3 Answers 3

5

I needed this exact same thing for a form I was making and this is what I came up with to add the refs to the child components automatically

Given that you have:

<Parent>
    <Child />
    <Child />
</Parent>

You can use this in the Parent component render function to add a ref to every child.

render () {
  let wrappedChildren = [];

  React.Children.map(this.props.children, (child, i)=> {
    if (!child) {
      return;
    }
      let refName = 'child' + i
      wrappedChildren.push(React.cloneElement(child, {
        key: refName,
        ref: refName,
      }
    ));
  }, this);
  return (
    <View>
        {wrappedChildren}
    </View>
  )
}

This will add a ref to every Child consisting of a string plus the index of the current map and then render them in the same order, giving you the equivalent of doing this:

<Parent>
    <Child ref="child0" />
    <Child ref="child1" />
</Parent>

I know that string refs are deprecated but i was trying to keep it simple you can also use refs as callbacks by changing:

ref: refName

to:

ref: (c) => { this[refName] = c }

And then used it in the parent component as this.child0 for example.

Hope it helps.

Sign up to request clarification or add additional context in comments.

Comments

3

In this approach the Parent component is the one where the children are being used in render. You can manipulate the childrens' "state" by calling a method of them.

Parent.js

class Parent extends Component {
  refs = [];

  componentDidMount() {
    this.refs[0].doSelect();
  }

  setRef = ref => {
    this.refs.push(ref);
  }

  render() {
    return (
      <div>
        <Child ref={this.setRef} />
        <Child ref={this.setRef} />
      </div>
     )
   }
}

Child.js

class Child extends Component {
  state = { isSelected: false }

  doSelect = () => {
    this.setState({ isSelected: true })
  }

  render() {
    return <div className="child" />
  }
}

Comments

2
  1. I want the parent to be able to access the Child components' state.

State is only accessible to component itself. Parent and child component can access only their own state. You can pass value to child state as props but parent can't access child component state itself.

  1. Setting Refs to child component.

    Why do you want this? Ref is for
    Managing focus, text selection, or media playback.
    Triggering imperative animations.
    Integrating with third-party DOM libraries.

    Please visit this link to understand the uses of Ref.
    https://facebook.github.io/react/docs/refs-and-the-dom.html

Anyway, components can have their own refs, and you can set ref to child components,

render: function() {
    return (
      <div>
        <Child ref="child" />
        <div><button onClick={this.handleClick}>ACCESS REF</button></div>
      </div>
    );
  },

handleClick: function() {
    alert(this.refs.child.refs.input.getDOMNode().value);
  }
});

let Child = React.createClass({
  render: function() {
    return <input ref="input" />;
  }
});

I will suggest , you should either pass callbacks into children as props to do your stuff.:

8 Comments

so you can't add a ref during the constructor?
you are totally going wrong way. First go through answer and link posted.
ehh, it's a weird use case, I'm repurposing React components for something outside of web dev so it might not be awful
how would you set the ref on create?
<Child ref="child" />
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.