admin管理员组

文章数量:1313808

So, I have multiple ReactComponent. Initially, I was thinking that there will be sort of a parent ponent (let's call this GrandPa) with its own state, and it will pass down some info about its state to another ponent (call it Parent). Similarly, Parent passes some of his to Child and child to GrandChild. So we have the hierarchy:

GrandPa -> Parent -> Child -> GrandChild

However, I quickly realized that when I change the state of GrandPa with method this.setState(prevState => (<new state based on prevState>)), the changes do not cascade down the channel. Another problem I realized is passing changes up the channel as well. I have not found a nice way to do this. (Before, I did something super sketchy by binding some events to a ponent in the DOM and having a public variable that is accessible from all of the ReactComponent. Then when anyone triggers a specific event, I would try to trigger events that would update the respective ponents... Long story short, this created a lot of problems and was ugly.)

So, I have the example code below where I tried to do this with just a parent and child. It's a dummy example, but it's just to learn how to do this. The parent, called ReactRandom has a state {name: <name>} and has a method that changes that name to a random string. When ReactRandom renders, it renders that name from another ponent ReactRandomNested which basically prints out the name passed via its own props. Here, I created a method inside of ReactRandomNested which explicitly renders the changes (which I DO NOT WANT BTW, I am thinking there is a way to cascade the updates down the channel without having to explicitly do that because it'd get nasty quicky as we have >2 nested levels). However, even this does not work. It has a 1 step delay and renders the previous update at the current timestep.

Anyway, here's the code I currently have:

class RandomReactNested extends React.Component {
    constructor(props) {
        super(props);
        this.state = {name: props.name};
    }

    handleChange() {
        let self = this;
        self.setState({name: self.props.name});
    }

    render() {
        let self = this;
        return React.createElement("span", {
            onClick: () => self.handleChange.call(this)
        }, self.state.name);
    }
}

class RandomReact extends React.Component {
    constructor (props){
        super(props);
        this.state = {name: props.name};
        this.changeName.bind(this);
    }

    changeName () {
        let random_word_length = Math.round(Math.random()*20),
            index_count = 0,
            new_name = "",
            alphabet = "abcdefghijklmnopqrstuvwxyz";
        for (index_count; index_count <= random_word_length; index_count += 1) {
            new_name += `${alphabet[Math.round(Math.random()*random_word_length)]}`;
        }
        console.log(new_name);

        this.setState(prevState => ({
            name: new_name
        }));
    }

    render() {
        let self = this;
        return React.createElement("div", {
            key: 2,
            onClick: () => (this.changeName.call(self))
        },
            React.createElement(RandomReactNested, {
                name: self.state.name
            }));
    }
}

By the way, I am quite new to React and am trying to learn how to use this effectively. I also saw this from the ReactJS website toward the end of the page (.html), which seems to advice against this (but I am not entirely sure?):

"So What About Inheritance? At Facebook, we use React in thousands of ponents, and we haven’t found any use cases where we would remend creating ponent inheritance hierarchies. Props and position give you all the flexibility you need to customize a ponent’s look and behavior in an explicit and safe way. Remember that ponents may accept arbitrary props, including primitive values, React elements, or functions. If you want to reuse non-UI functionality between ponents, we suggest extracting it into a separate JavaScript module. The ponents may import it and use that function, object, or a class, without extending it."

So, I have multiple ReactComponent. Initially, I was thinking that there will be sort of a parent ponent (let's call this GrandPa) with its own state, and it will pass down some info about its state to another ponent (call it Parent). Similarly, Parent passes some of his to Child and child to GrandChild. So we have the hierarchy:

GrandPa -> Parent -> Child -> GrandChild

However, I quickly realized that when I change the state of GrandPa with method this.setState(prevState => (<new state based on prevState>)), the changes do not cascade down the channel. Another problem I realized is passing changes up the channel as well. I have not found a nice way to do this. (Before, I did something super sketchy by binding some events to a ponent in the DOM and having a public variable that is accessible from all of the ReactComponent. Then when anyone triggers a specific event, I would try to trigger events that would update the respective ponents... Long story short, this created a lot of problems and was ugly.)

So, I have the example code below where I tried to do this with just a parent and child. It's a dummy example, but it's just to learn how to do this. The parent, called ReactRandom has a state {name: <name>} and has a method that changes that name to a random string. When ReactRandom renders, it renders that name from another ponent ReactRandomNested which basically prints out the name passed via its own props. Here, I created a method inside of ReactRandomNested which explicitly renders the changes (which I DO NOT WANT BTW, I am thinking there is a way to cascade the updates down the channel without having to explicitly do that because it'd get nasty quicky as we have >2 nested levels). However, even this does not work. It has a 1 step delay and renders the previous update at the current timestep.

Anyway, here's the code I currently have:

class RandomReactNested extends React.Component {
    constructor(props) {
        super(props);
        this.state = {name: props.name};
    }

    handleChange() {
        let self = this;
        self.setState({name: self.props.name});
    }

    render() {
        let self = this;
        return React.createElement("span", {
            onClick: () => self.handleChange.call(this)
        }, self.state.name);
    }
}

class RandomReact extends React.Component {
    constructor (props){
        super(props);
        this.state = {name: props.name};
        this.changeName.bind(this);
    }

    changeName () {
        let random_word_length = Math.round(Math.random()*20),
            index_count = 0,
            new_name = "",
            alphabet = "abcdefghijklmnopqrstuvwxyz";
        for (index_count; index_count <= random_word_length; index_count += 1) {
            new_name += `${alphabet[Math.round(Math.random()*random_word_length)]}`;
        }
        console.log(new_name);

        this.setState(prevState => ({
            name: new_name
        }));
    }

    render() {
        let self = this;
        return React.createElement("div", {
            key: 2,
            onClick: () => (this.changeName.call(self))
        },
            React.createElement(RandomReactNested, {
                name: self.state.name
            }));
    }
}

By the way, I am quite new to React and am trying to learn how to use this effectively. I also saw this from the ReactJS website toward the end of the page (https://reactjs/docs/position-vs-inheritance.html), which seems to advice against this (but I am not entirely sure?):

"So What About Inheritance? At Facebook, we use React in thousands of ponents, and we haven’t found any use cases where we would remend creating ponent inheritance hierarchies. Props and position give you all the flexibility you need to customize a ponent’s look and behavior in an explicit and safe way. Remember that ponents may accept arbitrary props, including primitive values, React elements, or functions. If you want to reuse non-UI functionality between ponents, we suggest extracting it into a separate JavaScript module. The ponents may import it and use that function, object, or a class, without extending it."

Share Improve this question asked Dec 17, 2017 at 18:34 Robert VunabandiRobert Vunabandi 1472 silver badges12 bronze badges 1
  • 1 Here's an answer to this that I found. x) stackoverflow./questions/46727804/… – Robert Vunabandi Commented Dec 17, 2017 at 18:40
Add a ment  | 

1 Answer 1

Reset to default 7

cough, redux, cough

Anyway, passing props is a one way street! You can pass things down, and use them, but you can't pass them up. The only way to manipulate a parent ponent is through passing an entire function as props.

updateGrandpaState(newData){
this.setState({ originalData: newData})
}

From your grandpa ponent you you would pass it down like this...

<ParentComponent updateGrandpaState={this.updateGrandpaState} />

And inside your parent ponent you can call

this.props.updateGrandpaState(parentComponentData)

Which will then fire the original function that lives in grandpaComponent, thus updating grandpaComponent State.

And yes, you can go further, forewarning, the deeper you go the uglier it gets...

Inside Grandpa

< ParentComponent updateGrandpaState={this.updateGrandpaState} /> 

Inside Parent

< ChildComponent updateGrandpaState={this.props.updateGrandpaState} />

Inside Child

this.props.updateGrandpaState(childComponentData)

When you go two levels deep I also console.log(this.props) on ponentDidMount while doing dev work.

To make things even cooler, you could even pass grandpaState down into ParentComponent to use, which you could hook up to ponentWillRecieveProps.....

<ParentComponent grandpaState={this.state} updateGrandpaState={this.updateGrandpaState} />

But honestly, once you learn redux, set it up a few times, it's really awesome and I would never not use it!

本文标签: javascriptDealing with Nested React Components39 State ChangesStack Overflow