【问题标题】:How to change React context programmatically?如何以编程方式更改 React 上下文?
【发布时间】:2018-09-12 18:32:48
【问题描述】:

我正在尝试使用新的 React 上下文来保存有关已登录用户的数据。

为此,我在一个名为 LoggedUserContext.js: 的文件中创建了一个上下文

import React from 'react';


export const LoggedUserContext = React.createContext(
  );

果然,现在我可以使用消费者在其他组件中访问所述上下文,例如我在这里所做的:

  <LoggedUserContext.Consumer>
       {user => (
       (LoggedUserContext.name) ? LoggedUserContext.name : 'Choose a user or create one';
       )}
   </LoggedUserContext.Consumer>

但显然,为了使这个系统有用,我需要在登录后修改我的上下文,以便它可以保存用户的数据。我正在使用 axios 调用 REST API,我需要将检索到的数据分配给我的上下文:

axios.get(`${SERVER_URL}/users/${this.state.id}`).then(response => { /*What should I do here?*/});

我认为在 React 的文档中没有办法做到这一点,但他们甚至提到保存登录用户的信息是他们考虑的上下文用例之一:

上下文旨在共享可被视为“全局”的数据 React 组件树,例如当前经过身份验证的用户, 主题或首选语言。例如,在下面的代码中,我们 手动穿过“主题”道具以设置按钮样式 组件:

那我该怎么做呢?

【问题讨论】:

    标签: javascript reactjs authentication react-context


    【解决方案1】:

    为了使用Context,您需要一个Provider,它带有一个值,该值可以来自组件的状态并被更新

    例如

    class App extends React.Component {
       state = {
          isAuth: false;
       }
       componentDidMount() {
          APIcall().then((res) => { this.setState({isAuth: res}) // update isAuth })
       }
       render() {
           <LoggedUserContext.Provider value={this.state.isAuth}>
               <Child />
           </LoggedUserContext.Provider>
       }
    }
    

    关于dynamic context的部分解释了它

    【讨论】:

    • 与另一个答案相同的问题:因此,如果我将用户登录到应用程序深处 2-3 级的组件中,并且我需要在整个应用程序中使用我的上下文,那么我仍然需要以某种方式将用户数据一直提升到应用程序状态以便我可以设置它?
    • 是的,如果您需要在整个应用程序中使用上下文,那么您需要一个顶级提供程序并提升状态
    • 这里可能是一个半愚蠢的问题,但是如果恶意用户只是从开发工具或其他东西中操纵状态怎么办? (API 显然会受到保护,但我很好奇)。
    【解决方案2】:

    将您的消费组件包装在提供者组件中:

    import React from 'react';
    
    const SERVER_URL = 'http://some_url.com';
    
    const LoggedUserContext = React.createContext();
    
    class App extends React.Component {
        state = {
            user: null,
            id: 123
        }
        componentDidMount() {
            axios.get(`${SERVER_URL}/users/${this.state.id}`).then(response => { 
                const user = response.data.user; // I can only guess here
                this.setState({user});
            });
        }
        render() {
            return (
                <LoggedUserContext.Provider value={this.state.user}>
                    <LoggedUserContext.Consumer>
                        {user => (
                            (user.name) ? user.name : 'Choose a user or create one';
                        )}
                    </LoggedUserContext.Consumer>
                </LoggedUserContext.Provider>
            );
        }
    }
    

    我给出了一个完整的例子,使其更加清晰(未经测试)。请参阅the docs 以获取具有更好组件组合的示例。

    【讨论】:

    • 因此,如果我将用户登录到应用程序深处 2-3 级的组件中,并且我需要在整个应用程序中使用该上下文,那么我仍然需要以某种方式提高用户数据一直到应用程序状态,以便我可以设置它?
    • 是的,上下文只能在提供组件内部访问,不能在外部访问。因此,如果您在所有应用程序中都需要这些数据,您应该考虑包装您的应用程序组件或类似组件。
    • 如果我将整个应用程序包装在提供程序中,然后必须从子组件更新它的值怎么办?比方说,在用户填写并提交表单之后?
    • 在这种情况下,您需要将事件处理程序向下传递给该组件。但听起来你的场景并不是真正的上下文 - 用户输入通常是本地状态。否则 - 考虑一个像 redux 这样的库。
    猜你喜欢
    • 1970-01-01
    • 2012-03-29
    • 1970-01-01
    • 1970-01-01
    • 2016-11-06
    • 2023-03-22
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    相关资源
    最近更新 更多