React Context API - How to Get Reference To State Object In Provider For A Conditional Method

試著忘記壹切 提交于 2019-12-13 03:54:29

问题


I am testing out React's Context API and have successfully passed down my state items and a method to a Consumer component. However, when I add some conditional logic to the method I am losing reference to the state object items. I get a "Cannot read property 'color' of undefined" error. How do I reference by color key in that state object so I can run the logic? Am I able to do this in the Provider component or am I only able to do this logic in the Consumer component?

Provider Container File - 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;

Consumer Component - 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;

回答1:


i think your approach is error prone. better when you create function outside state, and then pass down to ConsumerComp as a props, something like this:

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

}




回答2:


Thank you Chris. The issue is with the ES5 syntax. I needed to use a fat arrow syntax => to bind this to the component. This allowed me to access state in my logic. This is the working code. Note that with this process the context API allows one to skip sending props down multiple levels which is pretty cool.

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;


来源:https://stackoverflow.com/questions/51480718/react-context-api-how-to-get-reference-to-state-object-in-provider-for-a-condi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!