admin管理员组

文章数量:1415460

I am using a boilerplate called trufflebox's react-auth where

  1. getWeb is called on loading the page (Link to code)
  2. which creates the web3 object (Link to Code)
  3. and stores web3 in the Redux store (Link to code)

Problem: When I retrieve the web3 object from the Redux store, it is undefined, most likely because web3 has not been created yet in Step 2 described above.

What should be the correct way to retrieve web3 from the Redux store only after it has been set?

layouts/test/Test.js

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


class Test extends Component {

    ponentWillMount() {
        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

Everything works if I retrieve web3 again without going to the Redux store:

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


class Test extends Component {

    ponentWillMount() {
        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

I am using a boilerplate called trufflebox's react-auth where

  1. getWeb is called on loading the page (Link to code)
  2. which creates the web3 object (Link to Code)
  3. and stores web3 in the Redux store (Link to code)

Problem: When I retrieve the web3 object from the Redux store, it is undefined, most likely because web3 has not been created yet in Step 2 described above.

What should be the correct way to retrieve web3 from the Redux store only after it has been set?

layouts/test/Test.js

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


class Test extends Component {

    ponentWillMount() {
        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

Everything works if I retrieve web3 again without going to the Redux store:

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


class Test extends Component {

    ponentWillMount() {
        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
Share Improve this question asked Nov 11, 2017 at 18:42 NyxynyxNyxynyx 63.9k163 gold badges507 silver badges856 bronze badges 1
  • Were you able to solve this? Was my answer below able to help point you in the right direction? Please share your progress on this when you can. – scniro Commented Dec 30, 2017 at 18:20
Add a ment  | 

2 Answers 2

Reset to default 4

Resolve the promise just after creating the store

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;

In you ./index.js (where you are rendering the whole app) consider to use Provider ponent as wrapper to pass store behind the seen and have a singleton store.

src/index.js

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

        ReactDOM.render(

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

Now, in your ponent, connect HOC will do everything , see ments below :

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 ponent

        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 

Maybe try calling instantiateContract during the ponentWillReceiveProps phase. Check out the following...

ponentWillMount() {
  this.setState({
    web3: store.getState().results.payload.web3Instance
  });
}

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

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

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

where nextProps.whatever is what you are mapping from redux (not totally sure what this is given your details). Ideally this is getting fed back into your ponent and when the value either populates or changes, you then call your function


Also, I see a lot of state management here opposed to what I would expect to see done via props. if ponentWillReceiveProps(nextProps) is not a good hook given your application architecture, ponentDidUpdate(prevProps, prevState) could be a viable alternative.

本文标签: javascriptGet data from Redux Store after data has been addedStack Overflow