React Context API - Как получить ссылку на объект состояния в поставщике для условного метода
Я тестирую контекстный API React и успешно передал свои элементы состояния и метод компоненту потребителя. Однако, когда я добавляю некоторую условную логику в метод, я теряю ссылку на элементы объекта состояния. Я получаю сообщение об ошибке "Не удается прочитать свойство" цвет "неопределенного". Как мне ссылаться на цветовой ключ в этом объекте состояния, чтобы я мог запустить логику? Могу ли я сделать это в компоненте "Провайдер" или я могу использовать эту логику только в компоненте "Потребитель"?
Файл контейнера провайдера - ProviderComp.js
class ProviderComp extends Component{
state={
name: "Gary",
age: 20,
color: "Red",
changeMind: function(){
if(this.color === "Red"){
document.getElementById("root").style.background="blue";
document.getElementById("root").style.color="white";
this.setState({
name: "Tony",
age: 35,
color: "Blue"
})
}
if(this.color === "Blue"){
document.getElementById("root").style.background="red";
document.getElementById("root").style.color="black";
this.setState({
name: "Gary",
age: 20,
color: "Red"
})
}
}
}
render(){
return(
<UserInfo.Provider value={{state:this.state}}>
{this.props.children}
</UserInfo.Provider>
)
}
}
export default ProviderComp;
Потребительский компонент - ConsumerComp.js
import React, {Component} from "react";
import UserInfo from "./ContextData";
class ConsumerComp extends Component{
render(){
return(
<UserInfo.Consumer>
{(context)=>(
<React.Fragment>
<p>My Name Is: {context.state.name}</p>
<p>My Age Is: {context.state.age}</p>
<p>My Favorite Color Is: {context.state.color}</p>
<button onClick={context.state.changeMind}>Changed My Mind</button>
</React.Fragment>
)}
</UserInfo.Consumer>
)
}
}
export default ConsumerComp;
2 ответа
Спасибо, Крис. Проблема в синтаксисе ES5. Мне нужно было использовать синтаксис жирной стрелки =>, чтобы связать это с компонентом. Это позволило мне получить доступ к состоянию в моей логике. Это рабочий код. Обратите внимание, что с помощью этого процесса контекстный API позволяет пропустить отправку реквизита на несколько уровней, что довольно круто.
import React, {Component} from "react";
import UserInfo from "./ContextData";
class ProviderComp extends Component{
state={
name: "Gary",
age: 20,
color: "Red",
changeMind: ()=>{
if(this.state.color === "Red"){
document.getElementById("root").style.background="blue";
document.getElementById("root").style.color="white";
this.setState({
name: "Tony",
age: 35,
color: "Blue"
})
}
if(this.state.color === "Blue"){
document.getElementById("root").style.background="red";
document.getElementById("root").style.color="black";
this.setState({
name: "Gary",
age: 20,
color: "Red"
})
}
}
}
render(){
return(
<UserInfo.Provider value={{state:this.state}}>
{this.props.children}
</UserInfo.Provider>
)
}
}
export default ProviderComp;
Я думаю, что ваш подход подвержен ошибкам. лучше, когда вы создаете функцию вне состояния, а затем переходите к ConsumerComp
как реквизит, примерно так:
class ProviderComp extends Component{
state={
name: "Gary",
age: 20,
color: "Red"}
constructor(props){
super(props);
this.changeMind=this.changeMind.bind.this;
}
changeMind(){
if(this.state.color === "Red"){
// ...///
this.setState({
//...
})
}
}
///
render(){
<UserInfo.Provider value={{state:this.state}}>
{React.Children.map(children, (child, index) =>
React.cloneElement(child,{changeMind: this.changeMind})
)}
</UserInfo.Provider>
}
}