Martin Mazza Dawson Martin Mazza Dawson - 1 month ago 8
Javascript Question

Is passing the "this" context through props an anti-pattern?

I have two components, a parent and a child like so:

class Parent extends React.Component {
shuffle() {
...
}
blur() {
...
}
next() {
...
}
previous() {
...
}
render() {
return (
<Child Parent={this} />
);
}
}

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

this.state = {};

this._onShuffleClick = this._onShuffleClick.bind(props.Parent);
this._onPreviousClick = this._onPreviousClick.bind(props.Parent);
this._onNextClick = this._onNextClick.bind(props.Parent);
}
_onShuffleClick(event) {
event.preventDefault();

this.shuffled ? this.shuffle(false) : this.shuffle(true); // I can call parents method here as the 'this' context is the 'Parent'.
this.blur(event.target);
this.setState({test "test"}); //I can set the parents state here
}
_onPreviousClick(event) {
event.preventDefault();

this.previous();
this.blur(event.target);
}
_onNextClick(event) {
event.preventDefault();

this.next();
this.blur(event.target);
}
render() {
return (
<a className="shuffle" key={1} onClick={this._shuffleOnClick}>{this.props.Parent.props.html.shuffle}</a>,
<a className="previous" key={2} onClick={this._previousOnClick}>{this.props.Parent.props.html.previous}</a>,
<a className="next" key={3} onClick={this._nextOnClick}>{this.props.Parent.props.html.next}</a>,
);
}
}


Is passing the context ('this' keyword) as a prop an anti-pattern?
Is setting the state of the parent from the child bad?

If I do this I then don't have to pass a lot of individual props to the child and I can also set the state of the parent from the child.

Answer

You can interact with the state of a parent from a child-component, but probably not the way you are trying to achieve this.

If you want to send in all props of the parent down to a child, you can do:

<Child {...this.props} />

This way, you don't need to specify each individual prop one at a time; instead, you just send them all in. Check out the spread operator here and here for more info. More info also on MDN:

The spread syntax allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) or multiple variables (for destructuring assignment) are expected.


If you want to access or modify the state of a parent from a child you have to do this slightly differently. Typically, you would create a function that does this interaction with the state in your parent and then send that function as a prop down to the child. Like this:

Parent:

_modifyState = (bar) => {
  this.setState({foo: bar});
}
.....
<Child modifyState={this._modifyState} />

Child:

this.props.modifyState("Hello world!");

The above will set state.foo in the parent to the string Hello world! from the child component.

If you want access to all state variables, you could send it in as a prop to the child (the whole object) and then have a function (like above) which modifies the entire state (not just one property) - depends what you want really.

Comments