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.
Related
I have a parent component
class ParentComponent extends React.PureComponent {
render(){
return(
//IN HERE I'm calling child parent
<ChildComponent/>
)
}
}
class ChildComponent extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
sample: '',
};
}
how can I get the sample state to the parent component?
So at the Parent Component make a method which receives value in return.
StateValue = (value) =>{
console.log(value);
}
Pass this method as props to the child component.
<ChildComponent method={this.StateValue}/>
At the child component Pass the state value to the method props received in step 2.
constructor(props) {
super(props);
this.state = {
sample: 'hi',
};
}
render(){
this.props.method(this.state.sample)
return(
<></>
)
You will get your state value in StateValue Method from the props in your parent component.
Try this:
class ParentComponent extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
sample: '',
};
}
render(){
return(
<ChildComponent sample={this.state.sample} setState={(sample) => this.setState({ sample })} />
)
}
}
class ChildComponent extends React.PureComponent {
// you can now call this.props.setState(value); to set parent component state.
// and access the sample state: this.props.sample;
}
One option is to specify a callback as a prop. Like this:
class ParentComponent extends React.PureComponent {
onSample = (sample) => {
// handle sample
}
render(){
return(
//IN HERE I'm calling child parent
<ChildComponent
callback={this.onSample}
/>
)
}
}
class ChildComponent extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
sample: '',
};
this.onSample = props.callback
// call later on via this.onSample(<sample>);
}
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} />
}
}
import React from "react";
import ReactDOM from "react-dom";
class NestedComponent extends React.Component {
constructor(props) {
super(props);
this.childMethod = this.childMethod.bind(this);
}
childMethod() {
alert("Child method one ran");
}
render() {
return <div>NestedComponent</div>;
}
}
class NestedComponentTwo extends React.Component {
constructor(props) {
super(props);
this.childMethod = this.childMethod.bind(this);
}
childMethod() {
alert("Child method two ran");
}
render() {
return <div>NestedComponentTwo</div>;
}
}
class WrappingComponent extends React.Component {
constructor(props) {
super(props);
this.runMethod = this.runMethod.bind(this);
}
runMethod() {
let child = this.props.children[0];
/** Always returns as undefined */
//if (typeof child.childMethod == "function") {
// child.childMethod();
//}
/**
* EDIT: Close, however the this binding seems to not be working. I can however provide the childs props to the childMethod and work with that.
*/
if(typeof child.type.prototype.childMethod == "funciton"){
child.type.prototype.childMethod();
}
}
render() {
return (
<div>
{this.props.children}
<button onClick={this.runMethod}>run</button>
</div>
);
}
}
const App = ({}) => {
return (
<div>
<WrappingComponent>
<NestedComponent />
<NestedComponentTwo />
</WrappingComponent>
</div>
);
};
if (document.getElementById("example")) {
ReactDOM.render(<App />, document.getElementById("example"));
}
So the goal is to have optional methods attached to a nested component that can execute from the wrapping component, almost like an event emmiter. For some reason though, the method that exists on the child component claims not to exist. However whenever I log the child component pulled from the array of the this.props.children the prototype has the method listed.
Am I missing a special way to access methods of children components through a methods variable perhaps?
Found the variable I can use to access it. If anyone has any more insight into this, or reasons why what I am doing is poor practice please let me know.
Editing the question where this is needed, but the item below is accessing the function of the child:
child.type.prototype.childMethod
Does not appear to maintain the this binding. Passing props down does work however.
You should manage all of this logic in the top level component (the App component)
class NestedComponent extends React.Component {
constructor(props) {
super(props);
this.childMethod = this.childMethod.bind(this);
}
childMethod() {
alert("Child method one ran");
}
render() {
return <div>NestedComponent</div>;
}
}
class NestedComponentTwo extends React.Component {
constructor(props) {
super(props);
this.childMethod = this.childMethod.bind(this);
}
childMethod() {
alert("Child method two ran");
}
render() {
return <div>NestedComponentTwo</div>;
}
}
class WrappingComponent extends React.Component {
render() {
return (
<div>
{this.props.children}
<button onClick={this.props.onClick}>run</button>
</div>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.runMethod = this.runMethod.bind(this);
}
runMethod() {
if (this.nestedComponent) {
this.nestedComponent.childMethod();
}
}
render() {
return (
<div>
<WrappingComponent onClick={this.runMethod}>
<NestedComponent ref={el => this.nestedComponent = el} />
<NestedComponentTwo />
</WrappingComponent>
</div>
);
}
};
if (document.getElementById("example")) {
ReactDOM.render(<App />, document.getElementById("example"));
}
<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="example"></div>
Moreover ref with string attribute is deprecated https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs
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 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 });
}
}