Работа с изменениями состояния вложенных компонентов React

Итак, у меня есть несколько ReactComponent. Первоначально я думал, что будет своего рода родительский компонент (давайте назовем этот GrandPa) с его собственным состоянием, и он передаст некоторую информацию о своем состоянии другому компоненту (назовите его Parent). Точно так же Родитель передает часть своего ребенка и ребенка к GrandChild. Итак, у нас есть иерархия:

GrandPa -> Родитель -> Ребенок -> GrandChild

Тем не менее, я быстро понял, что, когда я изменяю состояние GrandPa с помощью метода this.setState(prevState => (<new state based on prevState>))изменения не касаются канала. Еще одна проблема, которую я понял, это передача изменений по каналу. Я не нашел хороший способ сделать это. (Раньше я делал что-то очень схематичное, связывая некоторые события с компонентом в DOM и имея открытую переменную, доступную из всех компонентов ReactComponent. Затем, когда кто-то запускает определенное событие, я пытался вызвать события, которые обновили бы соответствующие компоненты... Короче говоря, это создало много проблем и было некрасиво.)

Итак, у меня есть пример кода ниже, где я пытался сделать это только с родителем и ребенком. Это фиктивный пример, но он просто для того, чтобы научиться это делать. Родитель, называется ReactRandom имеет состояние {name: <name>} и имеет метод, который меняет это имя на случайную строку. когда ReactRandom делает это имя от другого компонента ReactRandomNested который в основном печатает имя, переданное через его собственный реквизит. Здесь я создал метод внутри ReactRandomNested который явно отображает изменения (которые я НЕ ХОЧУ, кстати, я думаю, что есть способ каскадировать обновления вниз по каналу без необходимости явно делать это, потому что это будет очень неприятно, так как у нас>2 вложенных уровня). Однако даже это не работает. Он имеет задержку в 1 шаг и отображает предыдущее обновление с текущим временным шагом.

В любом случае, вот код, который у меня сейчас есть:

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
            }));
    }
}

Кстати, я новичок в React и пытаюсь научиться использовать это эффективно. Я также видел это с веб-сайта ReactJS в конце страницы ( https://reactjs.org/docs/composition-vs-inheritance.html), что, кажется, советует против этого (но я не совсем уверен?):

"А как же Наследование? В Facebook мы используем React в тысячах компонентов, и мы не нашли ни одного случая использования, в котором мы бы рекомендовали создавать иерархии наследования компонентов. Реквизиты и композиция дают вам всю гибкость, необходимую для настройки внешнего вида компонента. и поведение явным и безопасным способом. Помните, что компоненты могут принимать произвольные реквизиты, в том числе примитивные значения, элементы React или функции. Если вы хотите повторно использовать функциональные возможности, не связанные с пользовательским интерфейсом, между компонентами, мы предлагаем извлечь их в отдельный модуль JavaScript. компоненты могут импортировать его и использовать эту функцию, объект или класс, не расширяя его."

1 ответ

Решение

кашель, избыточный, кашель

В любом случае, проезжающие мимо реквизиты - это улица с односторонним движением Вы можете передать вещи и использовать их, но вы не можете передать их. Единственный способ манипулировать родительским компонентом - передать всю функцию в качестве реквизита.

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

От твоего дедушкиного компонента ты бы передал его вот так...

<ParentComponent updateGrandpaState={this.updateGrandpaState} />

И внутри вашего родительского компонента вы можете позвонить

this.props.updateGrandpaState(parentComponentData)

Который затем запустит оригинальную функцию, которая живет в grandpaComponent, тем самым обновляя grandpaComponent State.

И да, вы можете идти дальше, предупреждая, чем глубже вы идете, тем страшнее становится...

Внутри дедушка

< ParentComponent updateGrandpaState={this.updateGrandpaState} /> 

Внутри родителя

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

Внутри ребенка

this.props.updateGrandpaState(childComponentData)

Когда вы углубляетесь на два уровня, я также console.log(this.props) на componentDidMount, пока выполняю работу разработчика.

Чтобы сделать вещи еще круче, вы можете даже передать grandpaState в ParentComponent для использования, которое вы можете подключить к componentWillRecieveProps.....

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

Но, честно говоря, как только вы изучите лексему, настройте ее несколько раз, это действительно круто, и я бы никогда не использовал ее!

Другие вопросы по тегам