Работа с изменениями состояния вложенных компонентов 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} />
Но, честно говоря, как только вы изучите лексему, настройте ее несколько раз, это действительно круто, и я бы никогда не использовал ее!