I am trying to convert my React classes to ES6, but I am having some difficulty within this process.. I would like to have my bindings in the constructor, not in the render view.
Now, if I have a root module with a setState which needs a parameter, e.g.:
constructor() {
super();
this.state = {
mood: ""
};
this.updateMood(value) = this.updateMood.bind(this,value);
}
updateMood(value) {
this.setState({mood: value});
}
Then I pass this function to a component:
<customElement updateMood={this.updateMood}></customElement>
Then within the customElement module, I have something like this:
constructor() {
super();
}
update(e) {
this.props.updateMood(e.target.value);
}
and in the render:
<input onChange={this.update} />
Is this the correct way? Since I can't get it to work ;-(
You can't use this this.updateMood(value) = this.updateMood.bind(this,value); construction, because it is syntax error.
You can solve your problem like this
class CustomElement extends React.Component {
constructor() {
super();
this.update = this.update.bind(this);
}
update(e) {
this.props.updateMood(e.target.value);
}
render() {
return <input onChange={this.update} />
}
}
class Parent extends React.Component {
constructor() {
super();
this.state = {
mood: ""
};
this.updateMood = this.updateMood.bind(this);
}
updateMood(value) {
this.setState({ mood: value });
}
render() {
return <div>
<CustomElement updateMood={this.updateMood}></CustomElement>
<h1>{ this.state.mood }</h1>
</div>
}
}
Example
Or, depending on your babel settings, or when using typescript, the following achieves the same but is a lot more convenient to write / maintain:
class Parent extends React.Component {
constructor() {
super();
this.state = {
mood: ""
};
}
updateMood = (value) => {
this.setState({ mood: value });
}
}
Related
I'm new to the world of React and I'm trying to build a parent component with a function that should be invoked from a child component. However, when I call the function, I get the error message in the title. I have something similar:
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.myFunction = this.myFunction.bind(this);
}
myFunction(param) {
//do something
}
render(){
return(
<ChildComponent event={this.myFunction} />
);
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
inheritedFunction: this.props.event
};
}
childFunction(param) {
//do a few things first
this.state.inheritedFunction(param);
}
render(){
return(
<input type="checkbox" onChange={this.childFunction.bind(this)></input>
);
}
}
My code compiles and runs, and then when it gets to execute the childFunction( ) upon selecting the checkbox, this.state.inheritedFunction(param) says that it is not a function and the application collapses. I suspect that it has to do something with binding, but I'm really not sure and stuck with this problem.
I'm new to React, so please be nice. :-) Anyone knows what I messed up?
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.myFunction = this.myFunction.bind(this);
}
myFunction = (param) => {
//do something
alert(param);
}
render(){
return(
<ChildComponent event={this.myFunction} />
);
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
inheritedFunction: this.props.event
};
}
childFunction(param) {
//do a few things first
this.props.event(param);
}
render(){
return(
<input type="checkbox" onChange={this.childFunction.bind(this)></input>
);
}
}
I think your problem is trying to save a reference inside the state and then on the onchange callback you are binding again the function.
remove the state on the constructor and just call it directly from props
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.myFunction = this.myFunction.bind(this);
}
myFunction(param) {
//do something
}
render(){
return(
<ChildComponent event={this.myFunction} />
);
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.childFunction = this.childFunction.bind(this); // bind on the constructor.
}
childFunction() {
//do a few things first
this.props.event(this) //call the prop directly here.
}
render(){
return(
<input type="checkbox" onChange={this.childFunction></input> // no more binding here
);
}
}
class ParentComponent extends React.Component {
constructor(props) {
super(props);
}
myFunction = param => {
//do something
};
render() {
return <ChildComponent event={this.myFunction} />;
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
}
childFunction = (param) => {
//do a few things first
this.props.event(param);
}
render() {
return <input type="checkbox" onChange={this.childFunction} />
}
}
I need to inherit the state. Can I inherit the state? When I do this, I get an empty state.
class Example extends Component {
constructor(props) {
super();
this.state = {
param1:
};
}
...
}
class Example2 extends Example {
render() {
return (
{this.state.param1} // empty
)
}
}
You can extend state as follows:
constructor(props) {
super(props)
this.state = {
...this.state,
extraStuff: '',
}
}
Instead of using inheritance, you could use regular composition and pass the entire Example state as props to Example2 and use the props passed to Example2 as initial state.
Example
class Example extends React.Component {
state = {
param1: "test"
};
render() {
return <Example2 {...this.state} />;
}
}
class Example2 extends React.Component {
state = {...this.props};
render() {
return <div>{JSON.stringify(this.state)}</div>;
}
}
ReactDOM.render(<Example />, document.getElementById("root"));
<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="root"></div>
class Example extends Component {
constructor(props) {
super();
this.state = {
param1: "param1"
};
}
render() {
const { param1 } = this.state;
return (
<Example2 param1={param1} />
)
}
}
class Example2 extends Example {
render() {
const { param1 } = this.props;
return (
{param1}
)
}
}
Kovich. You can pass the state of one component to another only as props like this code:
class Example extends Component {
constructor(props) {
super();
this.state = {
param1:
};
}
render(){
return (<Example2 param1 ={this.state.param1} />)
}
...
}
class Example2 extends Example {
constructor(props) {
super();
this.state = {
param1: this.props.param1
};
}
render() {
return (
{this.state.param1} // empty
)
}
}
Inheritance is not really supported in React, you can find more information on this link:
https://reactjs.org/docs/composition-vs-inheritance.html#so-what-about-inheritance
What you can do is to have a global state manager (for example Redux) or pass the state to the Example2 component on the following way:
class Example extends Component {
constructor(props) {
super(props);
this.state = {
param1: 'test'
};
render() {
return (
<Example2 state={this.state} />
);
}
}
After that you will be able to reach it in Example2 by this.props.state.param1.
I have react component which returns an integer. Structure of the class component is as follows:
class MyClass extends Component {
constructor(props) {
super(props);
this.state = {
variable : 0
}
}
componentDidMount(){
// do some works
this.setSate({variable:$someValue});
}
render(){
var temp = this.state.variable;
return temp;
}
}
I need to fetch the value returned from MyClass in another class component in React within render.
If I call like,
render () {
return (
<div>{Myclass}</div>
);
}
it works fine. is there any way to call this outside return, and assign the value to a variable?
Try utilizing 'this.props' instead. You can pass in something like this
class MyClass extends Component {
constructor(props) {
super(props);
this.state = {
variable : 0
}
}
componentDidMount(){
// do some works
this.setSate({variable:$someValue});
}
render(){
const {variable} = this.state
return (
<MyOtherClass variable = {variable}/>
);
}
}
And in MyOtherClass:
render() {
const {variable} = this.props
return (
<div>{variable}</div>
);
}
You should be able to extend MyClass and call super.render()
class MyOtherClass extends MyClass {
render() {
const value = super.render();
return (
<div>{value}</div>
);
}
}
edit: working example in codesandbox.io
I want to update the value of 'change_color' in the second class and automatically render it in the first class when the value gets changed.
Assume, 'Second' component as the child of the 'First' component.
Solved it. Code is edited and it is the answer.
class First extends Component {
constructor() {
super();
this.state = {
change_color: false
}
this.handleChange = this.handleChange.bind(this);
}
handleChange() {
this.setState({
change_color: true
})
}
render() {
console.log(this.state.change_color);
return(<div><Second colorChange={this.handleChange} /></div>)
}
}
class Second extends Component {
constructor() {
super();
}
render() {
return(<div><button onClick={this.props.colorChange} /></div>)
}
}
Maybe you can try this, just make a container component, and set the value you want to change into a state of the container component, add a method to change the state value, then, you can use "this.props.handleColorChange" to call the method of the parent component in children components.
class ParentComponent extends Component {
constructor() {
super();
this.state = {
change_color: false
}
}
handleColorChange= () => {
const {change_color} = this.state;
this.setState = {
change_color: !change_color
}
}
render() {
const {change_color} = this.state,
{handleColorChange} = this;
return (
<div>
<ChildComponent1
color={change_color}
handleColorChange={handleColorChange}
/>
<ChildComponent2
color={change_color}
handleColorChange={handleColorChange}
/>
</div>
);
}
}
class ChildComponent1 extends Component {
constructor() {
super();
}
render() {
const {color} = this.props;
return(
<span>now, the color is {color}</span>
)
}
}
class ChildComponent2 extends Component {
constructor() {
super();
}
const {handleColorChange} = this.props;
return(
<button onClick={handleColorChange}>click to change color</button>
)
}
What you need to do is lifting up the state. Create a new component that has a state with the colour and the change colour function. Then pass to first and second componentes the corresponding properties as props and inside of them call the function to change the colour. Does it makes sense?
I need to create an element that, when rendered, loads its own data and displays it. I wrote something like this:
export default class MyComponent extends React.Component {
constructor() {
super();
this.state = {
content: "Loading..."
};
}
render() {
Data.singleton().load(0, 100, "desc").then((function(data) {
this.setState({
content: {JSON.stringify(data, null, 3)}
});
}).bind(this));
return <pre>{this.state.content}</pre>
}
}
Now, this works but the react documentation clearly states that:
The render() function should be pure, meaning that it does not modify
component state
So I was wondering what's the best design pattern for this kind of needs.
p.s.: I know I could load the data in the containing element and pass it in to MyComponent using props. I am also aware that that seems "the way" to go with react but I was wondering if there are other legitimate ways.
Thanks
Here is an example: JSFiddle
This should be handled in componentDidMount (note, I'm using a setTimeout, to 'simulate' the async call):
class Main extends React.Component{
constructor(props){
super(props);
this.state = {
data: 'Loading...'
}
}
componentDidMount() {
console.log('Mounted');
setTimeout(() => {
this.setState({
data: 'set after waiting 2 seconds'
})
}, 2000)
}
//
render() {
return (
<div>{this.state.data}</div>
);
}
}
It looks like all you need to do is toss that function into componentDidMount or componentWillMount, like so:
componentDidMount() {
// state-altering logic
}
render() {
return <pre>{this.state.content}</pre>
}
https://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount
Since its recommended to have your ajax method in the componentDidMount
https://facebook.github.io/react/docs/component-specs.html#mounting-componentdidmount
You can structure your react component like this
export default class MyComponent extends React.Component {
constructor() {
super();
this.state = {
content: "Loading..."
};
}
componentDidMount(){
Data.singleton().load(0, 100, "desc").then((data)=> {
this.setState({
content: {JSON.stringify(data, null, 3)}
});
});
}
render() {
return <pre>{this.state.content}</pre>
}
}