在数据添加后从Redux Store获取数据

3

我正在使用一个名为trufflebox的react-auth脚手架(点击此处查看代码),其中:

  1. 在页面加载时调用getWeb函数(点击此处查看代码);
  2. getWeb函数创建web3对象(点击此处查看代码);
  3. web3对象存储在Redux store中(点击此处查看代码)。

问题:当我从Redux store中检索web3对象时,它是undefined,很可能是因为在第二步中web3尚未被创建。

解决方案:正确的方法是只有在第2步完成后才从Redux store中检索web3对象。

layouts/test/Test.js

import React, { Component } from 'react';
import store from '../../store';


class Test extends Component {

    componentWillMount() {
        this.setState({
            web3: store.getState().results.payload.web3Instance
        })
        this.instantiateContract()
    }

    instantiateContract() {
        console.log(this.state.web3)                             // UNDEFINED!!
    }


    render() {
        return (
            <h1>Test</h1>
        )
    }
}

export default Test

如果我不去访问Redux存储,只需再次检索web3,一切都可以正常工作:

import React, { Component } from 'react';
import getWeb3 from '../../util/web3/getWeb3';


class Test extends Component {

    componentWillMount() {
        getWeb3
        .then(results => {
            this.setState({
                web3: results.payload.web3Instance
            })
            this.instantiateContract()
        })
    }


    instantiateContract() {
        console.log(this.state.web3)
    }


    render() {
        return (
            <h1>Test</h1>
        )
    }
}

export default Test

你能解决这个问题吗?我的下面的答案是否有助于指引你正确的方向?请在你能时分享你的进展。 - scniro
2个回答

4
在创建store之后立即解决promise。 src/store.js
        import getWeb3 from './util/web3/getWeb3';
        import { createStore } from 'redux';

        //... prepare middlewares and other stuffs , then : create store
        const store = createStore(/*....configure it as you want..*/);

        // Just after creating store, here the engineering:

        getWeb3.then(results => {
          // Assuming you have suitable reducer
          // Assuming the reducer put the payload in state and accessible via "getState().results.payload.web3Instance"
          store.dispatch({ type: 'SAVE_WEB3', payload: results.payload.web3Instance });
        });


        export default store;

在你的 ./index.js 文件中(这里是你渲染整个应用程序的地方),考虑使用 Provider 组件作为包装器来传递存储并拥有单例存储。

src/index.js

        import { Provider } from 'react-redux';
        import store from './store';

        ReactDOM.render(

          <Provider store={store}>
            <Test />
          </Provider>
        )

现在,在您的组件中,connect HOC将会做所有事情,请参见下面的注释:

src/.../Test.js

        import { connect } from 'react-redux';


        class Test extends Component {
           // No need any lifecyle method , "connect" will do everything :)

            render() {
                console.log(this.props.web3)      
                return (
                    <h1>Test</h1>
                )
            }
        }
        // Retrieve from Redux STATE and refresh PROPS of component

        function mapStateToProps(state) {
          return {
            web3: state.results.payload.web3Instance  // since you are using "getState().results.payload.web3Instance"
          }
        }
        export default connect(mapStateToProps)(Test); // the awesome "connect" will refresh props 

2
也许尝试在 componentWillReceiveProps 阶段调用 instantiateContract。请查看以下内容...
componentWillMount() {
  this.setState({
    web3: store.getState().results.payload.web3Instance
  });
}

instantiateContract() {
  console.log(this.state.web3); // hopefully not undefined                           
}

componentWillReceiveProps(nextProps) {
  if(nextProps.whatever) {
    this.instantiateContract();
  }
}

render() {
  return (
    <h1>Test</h1>
  )
}

其中nextProps.whatever是从redux映射过来的(根据您的详细信息,不确定这是什么)。理想情况下,它将被反馈到组件中,当值填充或更改时,您就可以调用函数。


此外,我看到很多状态管理,而不是我所期望的通过props完成。如果componentWillReceiveProps(nextProps)钩子在应用程序架构中不合适,则componentDidUpdate(prevProps, prevState)可能是一个可行的替代方法。


你建议在 index.js 中先获取 web3 对象,然后将其作为属性传递给 Test 组件吗?这样做是否可行? - Nyxynyx
无论web3是什么,这个一次性的应用程序设置是你在运行应用程序之前基本上想要的吗?如果是这样,那就完全可以。我不知道你的应用程序的完整架构,但根据你的一些命名,我倾向于我的直觉是真实的。如果可以的话,我会完全放弃.setState。通过_reducer_分派您的事件,在存储中设置值,映射它,然后结束。如果这是一个真正的异步调用,您将希望利用生命周期事件挂钩来检查它,如我上面所提到的。如果您能在应用程序运行之前制作它,那就更好了,因为您已经在安装时拥有它。 - scniro
@Nyxynyx 你解决了吗?请在方便的时候分享一下你的进展。 - scniro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接