How to pass state with parent to child component - javascript

Is there any way passing state from parent component to child component like:
var ParentComponent = React.createClass({
getInitialState: function() {
return {
minPrice: 0
}
},
render: function() {
return (
<div onClick={this.doSomething.bind(this, 5)}></div>
);
}
});
var ChildComponent = React.createClass({
getInitialState: function() {
return {
minPrice: // Get from parent state
}
},
doSomething: function(v) {
this.setState({minPrice: v});
},
render: function() {
return (
<div></div>
);
}
});
I want to change parent state value from child component. In react.js is it possible or not?

There is but it's not intended to work like that in React.
2-way data binding isn't the way to go in React, excerpt from the docs.
In React, data flows one way: from owner to child.
So what you want to do if you want to manipulate parent state in your child component is passing a listener.
//parent component's render function
return (
<Child listenerFromParent={this.doSomething} />
)
//child component's render function
return (
<div onClick={this.props.listenerFromParent}></div>
)

You can use the limelights solution, ie passing a function from the parent to the child.
Or you can also use projects like React-Cursor which permits to easily manipulate state passed from a parent component in a child.
I have made my home made framework (Atom-React, some details here) that also use cursors (inspired by Om), and you can somehow achieve easily 2-way data binding with cursors permitting to manipulate the state managed by a parent component.
Here's an exemple usage:
<input type="text" valueLink={this.linkCursor(this.props.inputTextCursor)}/>
The inputTextCursor is a cursor passed from a parent to a child component, and thus the child can easily change the data of the parent seemlessly.
I don't know if other cursor-based React wrappers use this kind of trick but the linkCursor function is implemented very easily with a simple mixin:
var ReactLink = require("react/lib/ReactLink");
var WithCursorLinkingMixin = {
linkCursor: function(cursor) {
return new ReactLink(
cursor.getOrElse(""),
function setCursorNewValue(value) {
cursor.set(value);
}
);
}
};
exports.WithCursorLinkingMixin = WithCursorLinkingMixin;
So you can easily port this behavior to React-Cursor

Related

pass value from child to parent component in react

I have component A and B. Component A pass state as prop to component, says it's named show
so in my component B's render function it will be like this
{this.props.show &&
<div>popup content</div>
}
But how I close it now? I have to pass a flag from component B to the parent? as I know it react you can pass stuff back to parent.
In order to pass data from a child to a parent, the parent needs to pass a function capable of handling that data to the child.
var Parent = React.createClass({
getData: function(data){
this.setState({childData: data});
}
render: function(){
return(
<Child sendData={this.getData} />
);
}
});
var Child = React.createClass({
textChange: function(event){
this.setState({textString: event.target.value});
}
buttonClick: function(){
this.props.sendData(this.state.textString);
}
render: function(){
<div>
<input type="text" value={this.state.textString}
onChange={this.textChange}/>
<button onClick={this.buttonClick}
</div>
}
});
There are other ways of handling data, and it might be worth your while creating a data store to store global variables and handle various events. In this way you would keep the data flow of your application one way. In smaller scale cases however, this solution should suffice.
Use the eventBus to send/receive date from child/parent components respectively.
Example below:
class Date extends Component {
constructor(props) {
super(props);
this.state = {
date:'',
}
this.callback = this.callback.bind(this); // register callback method
}
callback(date){ // callback method to receive data
this.setState({date: date});
}
componentDidMount(){
EventBus.on("date", this.callback);
}
render() {
<div>
{this.state.date}
</div>
}
}
From any other component
handleDayClick(day) {
EventBus.publish("date", day);
}
https://github.com/arkency/event-bus

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.
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.
Well, it's mainly a bad usage of passing around the props, you could also go for {...props} instead, and I wouldn't want to pass it through the full name, you can also use let { props } = this; let parentProps = props.Parent.props. The question is also, why would you refer to parent props, that seems the bad practise, divide and conquor, only pass the props that are really needed, and do not assume in your child components that a certain parent component is available
When you pass event handlers down, let those eventhandlers be bound to your current this, but don't bind them in the child to an expected parent, a bit like this example
var StyledButton = React.createClass({
propTypes: {
clickHandler: React.PropTypes.func.Required,
text: React.PropTypes.string.required
},
render: function() {
let { clickHandler, text } = this.props;
return <button type="button" onClick={clickHandler}>{text}</button>;
}
});
var MyForm = React.createClass({
click: function() {
alert('ouch');
},
render: function() {
return <fieldset>
<StyledButton clickHandler={this.click} text="Click me" />
</fieldset>
}
})
ReactDOM.render(
<MyForm />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
Yes I do think your code is bad practice. Now you chid components know about the parent component which makes your child impure.
When your parent implementation changes, the child components will break because of this.props.Parent.props.html.previous}.
I think each react component should update the parent by calling the parents functions passed by the props.
class Parent extends React.Component {
doSomethingBeacauseTheChildStateHasChanged() {
// function
}
render() {
<Child doSomething={doSomethingBeacauseTheChildStateHasChanged.bind(this)}/>
}
}
class Child extends React.Component {
render() {
<button onClick={this.props.doSomething}>Child button</button>
}
}
Note: I am not an expert and React beginner, treat this as an opinion rather than guideline.
I think yes cause you force particular implementation. What would you do if you wanted to have those methods in GrandParent? If you use props this modification is really easy, but with your implementation it would be pain in the ass.
There is also a feature called PropTypes. It's really great to make components reusable, but it's yet another thing you can't use if you do the things like you have proposed.
Maybe it is just me but this also creates a great confusion. You should pass everything you need as props.
Also setting parent state like this
this.setState({test "test"}); //I can set the parents state here
seems bad to me. I would rather pass a function from parent as a prop and bind parent before passing it down.
You can trigger a function in the Parent. This is the correct way to a children communicates with its parent.
class Parent extends React.Component {
shuffle(e) {
console.log(e.target);
return false;
}
render() {
return (
<Child onShuffle={this.shuffle} />
);
}
}
class Child extends React.Component {
render() {
return(
<a href='#' onClick={this.props.onShuffle}>Shuffle</a>
);
}
}
Child.propTypes = {
onShuffle: React.PropTypes.func
}

Communicate between parent and child component in React.js

Just meet a problem about communication between parent and child component in React.
Child
var Child = React.createClass({
getInitialState() {
return {
childState: this.props.state,
};
},
changeState(e) {
this.setState({e.target.id});
},
render: function () {
return (
<button id='1' onClick={this.changeState}>1</button>
<button id='2' onClick={this.changeState}>2</button>
);
},
});
Parent
var Parent = React.createClass({
getInitialState() {
return {
parentState: '1',
};
},
render: function () {
return (
<Child state=this.state.parentState />
);
},
});
So right now Parent will pass the initial state '1' to child, I want the child component can change both child and parent's state. For example, when click the second button, both child and parent state are set to '2'. How can I achieve this? Thank guys!
to achieve this behaviour you need to communicate with your parent component through props.
var Child = React.createClass({
render: function () {
return (
<button id='1' onClick={this.props.changeState}>1</button>
<button id='2' onClick={this.props.changeState}>2</button>
);
},
});
var Parent = React.createClass({
getInitialState() {
return {
parentState: '1',
};
},
changeState: function(){
this.setState({parentState: e.target.id});
},
render: function () {
return (
<Child changeState={this.changeState} state={this.state.parentState} />
);
},
});
The idea behind this is, that you are passing down the changeState function from your parent Component to your child Component as a function and make it accessible through props. That way when you call the prop function in your child Component - the function in the parent Component will get executed.
That way you also don't need to keep a second "separate" state in your child component because the state of the parent component will be available in both and have the same value in both.
Pardon me for any typing mistakes - I am at the office but since you had no answer yet I wanted to help.

Access child component state in other ways than ref?

I am unable to use something like this.refs.child.state in my application to access state of a child component, hence need an alternative way to do so. Main reason for this is to pass child contents to redux state when a certain button is clicked inside such childs parent component, hence function in parent component needs to pass childs content as one of the parameters.
Depending on the structure of your components (hard to tell when you don't post code), you could fix this just by chaining callbacks via props. I.e.
var Parent = React.createClass({
onChange: function(childValue){
this.setState({childValue: childValue});
},
render: function(){
return <Child onChange={this.onChange} />
}
});
var Child = React.createClass({
handleChange: function(event){
this.props.onChange(event.target.value);
},
render: function(){
return <input onChange={this.handleChange}/>
}
});
Add in as many middle-layers as needed of the form;
var MiddleChildA = React.createClass({
render: function(){
return <MiddleChildB onChange={this.props.onChange} />
}
});

ReactJS - Assign context/owner in 13.x

I am trying to render a child element that has already been initialized and is passed through a prop. My child depends on its context, yet I don't know how to apply that context before a render. Example:
http://jsfiddle.net/5qyqceaj/1/ (code below on React 0.13.3):
var Parent = React.createClass({
childContextTypes: {
test: React.PropTypes.string
},
getChildContext: function() {
return { test: "Working :)" };
},
render: function() {
return (
<div>
<b>Initialized Globally:</b><br/> {this.props.child}
<hr/>
<b>Initialized Inline:</b><br/> <Child/>
</div>
);
}
});
var Child = React.createClass({
contextTypes: {
test: React.PropTypes.string
},
render: function() {
return <div><h1>Context: {this.context.test || "Broken"}</h1></div>;
}
});
var ChildInstance = <Child/>;
React.render(<Parent child={ChildInstance} />, document.getElementById('container'));
In the example above, <Child/> when initialized globally fails to inherit the context passed by Parent.
According to https://github.com/facebook/react/issues/3451#issuecomment-104978224, this is an open issue with React 0.13.x where context is currently assigned via the owner and by 0.14 they will have it inherited from parents.
There are 3 ways I can imagine solving this:
Find a way to assign context within a component upon render or manually switch the owner of an element.
Reconstruct elements by passing in props and tagnames
Wait for 0.14
2 is really un-maintainable for more complicated structures and 3 is the surrender, is there any ways I can achieve 1?
You can use React.cloneElement to re-assign the owner of a React element. It will return a new element. Note that you will need to pass a new ref property, otherwise the previous owner will be preserved.
In your case, you would clone this.props.child in the render method of Parent.

Categories

Resources