Javascript 如何为每个组件提供一个值?

Javascript 如何为每个组件提供一个值?,javascript,reactjs,react-native,Javascript,Reactjs,React Native,我对本地人的反应有些生疏 我试图为每个组件添加一个值,本质上是登录信息 我正在使用这个库: 您可以通过以下方式获得登录信息: import Login from 'react-native-login-keycloak'; const gatheredTokens = await Login.getTokens(); 现在很明显,等待需要在异步函数中,所以我尝试如下: async componentWillMount() { const gatheredTokens = awai

我对本地人的反应有些生疏

我试图为每个组件添加一个值,本质上是登录信息

我正在使用这个库:

您可以通过以下方式获得登录信息:

import Login from 'react-native-login-keycloak';


const gatheredTokens = await Login.getTokens();
现在很明显,等待需要在异步函数中,所以我尝试如下:

async componentWillMount() {
    const gatheredTokens = await Login.getTokens();
    this.setState({ gatheredTokens: this.state.gatheredTokens });
}
然而这看起来很混乱——首先,componentWillMount显然被弃用了(我想我可以改为componentDidMount),而且它还要求我在每个组件中复制这个过程。混乱的代码复制

更纯粹的方法是什么?我猜是沿着高阶组件或其他结构的方向


有人能给我举个例子,说明我将如何向我的所有组件提供此功能(我使用的是Redux,因此通过Redux或其他方法就可以了)-我只是不确定如何确保数据在需要的任何地方都能得到处理和使用,我最想要的是“反应”方式。

有多种方法可以做到这一点,渲染道具,高阶组件,甚至挂钩-不确定在我写这个挂钩的时候是否支持React Native

无论如何,既然您建议使用高阶组件,那么我的解决方案将使用高阶组件

export const withGatheredTokens = Component => {
  class WithGatheredTokens extends React.Component {
    state = { gatheredTokens: null };

    async componentDidMount() {
        const gatheredTokens = await Login.getTokens();
        this.setState({ gatheredTokens });
    }

    render() {
      return (
        <Component gatheredTokens={this.state.gatheredTokens} {...props} />
      );
    }
  }

  return WithGatheredTokens;
};

// And this is how you use with with a Another Component
export AnotherComponent =  withGatheredTokens(AnotherComponentBase)
export const with gatheredtokens=Component=>{
使用GatheredTokens扩展React.Component的类{
state={gatheredTokens:null};
异步组件didmount(){
const gatheredTokens=wait Login.getTokens();
this.setState({gatheredTokens});
}
render(){
返回(
);
}
}
带着收集的票返回;
};
//这就是如何使用另一个组件
导出另一个组件=使用GatheredTokens(另一个组件库)
无论如何,网络请求应该始终在ComponendDupDate中完成,而不是componentWillMount方法。

使用Redux

创建您的
操作
还原器

//您可以将您的操作文件命名为loginAction.js

export const setLoginData = data => {
  return {
    type: SET_LOGIN_TOKEN,
    payload: data
  }
};
//和你的减速机一样

export default (state = {}, action = {}) => {
   switch (action.type) {
      case SET_LOGIN_DATA:
         return {...state, loginData: action.payload};

      default:
        return state;
   }
}
//别忘了将您的应用商店应用到
App.js
包装
查看
//

使用 在登录时,当您获得令牌时

async componentDidMount() {
   const gatheredTokens = await Login.getTokens();
   this.setState({ gatheredTokens: gatheredTokens });
   //this.setLoginData(gatheredTokens); 
   //having imported `setLoginData` from your login action, and also used `mapDispatchToProps`
}
那么你的登录数据应该在你需要的任何地方都可以使用

const mapStateToProps = (state) => ({
   loginData: state.loginData,
});
然后,您可以通过以下方式访问loginData中的令牌:

const loginToken = this.props.loginData;

您可以从父组件获取此数据,并将其作为道具传递给每个子组件。如果您使用的是redux,则只需将其设置为中心状态,并将其映射到需要访问数据的任何组件。redux文档中有很多例子:使用redux选择器
mapStateToProps
或将它们作为父组件的道具向下传递。@MattAft-我是在我的store.js中还是在单独的action/reducer中这样做?你能写一个简单的例子吗?我或多或少了解Redux,但我只使用了几个月。如果您希望能够修改状态值,则需要设置操作/缩减器。我提供的链接为您提供了一个简单todo应用程序的示例。问题还在于,如果应用程序关闭以自动登录,您是否希望保存此信息?因为这样您就可以使用RN的异步存储了:您认为这种方法还是HOC方法“更好”呢?我相信两者都可以。这取决于哪个最适合您的用例@CecilRodriguezI相信您的意思是这一行是this.setState({gatheredTokens:gatheredTokens})@塞西尔罗德里格斯是的,是的,我编辑了我的答案。您还可以在这里使用es6速记属性使代码更小(我在编辑中这样做了)@ehab Nice one。我认为这将在某种程度上起作用,对于我进入的每个包含导入组件的屏幕,如果
Login.getToken
未完成,它将不断地调用componentDidMount函数again@OluwasayoBabalola否,当安装组件时,只调用componentDidMount一次(除非组件被卸载并再次重新装载)。但是,在获取数据之前,包装好的组件将接收收集到的令牌作为null(我们指定的初始状态),并且一旦获取数据,HigherOrderComponent将重新呈现,并为其子级提供新的值gatheredTokens@ehab对,明白了。componentDidMount只被调用一次。有趣!我们将进一步阅读+1