Reputation: 3459
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.
Upvotes: 3
Views: 10413
Reputation: 6691
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" />
}
}
Upvotes: 3
Reputation: 394
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.
Upvotes: 5
Reputation: 12093
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.
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.:
Upvotes: 2