javascript - Unable to pass Redux store beyond React Router -
i've set first react app using redux, react-router, , react-router-redux. i'm passing store <provider>
, can see it's available in provider's props, yay.
beyond point lost. it's not available in child <router>
unless explicitly add store well.
however, regardless of whether pass store directly <router>
, available via context
in child connect(app) layer (which don't understand well), time gets actual <app>
component, store isn't available in either props or context. know should available via props, cannot figure out why it's not getting passed down.
i've read lot of similar questions mine, none of approaches i've seen have solved problem. know it's i'm missing conceptually, related connect
and/or mapstate/dispatchtoprops
, , possibly getinitialstate
. i've spent last 2 weeks trying understand of this, i've seen enough videos , read enough articles...i need more specific advice in relation code have. i'm ui guy, app architecture not forte, least.
it seems there many possible approaches, , can't distill of them down identify problem is. i've seen multiple implementations of connect
, it's confusing! advice appreciated.
also, i'm using webpack-dev-server , don't quite understand implications of using hashhistory vs. browserhistory vs. browserhistory() html5 history api. using bunch of middleware code logging , devtools well, making things more confusing me, i've removed them.
index.js
import react 'react' import { render } 'react-dom' import { createstore } 'redux' import { provider } 'react-redux' import { router, hashhistory } 'react-router' import routes './routes' import rootreducer './reducers' import { synchistorywithstore } 'react-router-redux' const initialstate = { errormessage: null } const store = createstore( rootreducer, initialstate, ) const history = synchistorywithstore(hashhistory, store) render ( <provider store={store}> <router history={history} routes={routes} /> </provider>, document.getelementbyid('root') )
app.js
import react, { component, proptypes } 'react' import { connect } 'react-redux' import { bindactioncreators } 'redux' import homepage './homepage' import { fetchprofileifexists, reseterrormessage } '../actions' class app extends component { constructor(props) { super(props) this.state = { isfetching: false } console.log('test', this.props) //log initial state //console.log('app state', store.getstate()) //every time state changes, log //note subscribe() returns function unregistering listener // store.subscribe(() => // { // var appchanges = store.getstate().registerapp; // this.setstate(appchanges); // console.log('app update', appchanges); // } // ) } componentdidmount() { // console.log(this.context) // this.context.store.subscribe(() => { // console.log('store', store.getstate().registerapp) // }) } componentwillreceiveprops(prevprops, nextprops) { //console.log('app componentwillreceiveprops', prevprops, nextprops) } componentdidupdate() { //console.log('app componentdidupdate') } rendererrormessage() { const { errormessage } = this.props if (!errormessage) return null return ( <p style={{ backgroundcolor: '#e99', padding: 10 }}> <b>{errormessage}</b> </p> ) } showloadingmessage() { var { isfetching } = this.props if (!isfetching) return null return <h2>loading...</h2> } render() { return ( <div classname='container-fluid' style={{ opacity: this.props.isfetching ? .5 : 1 }}> {this.rendererrormessage} {this.props.children} {this.showloadingmessage} </div> ); } } app.proptypes = { errormessage: proptypes.string, //reseterrormessage: proptypes.func.isrequired, children: proptypes.node, //store: proptypes.object.isrequired isfetching: proptypes.bool } // these props come application's state when started // function mapstatetoprops(state, ownprops) { // return { // ...state, // errormessage: state.errormessage, // test: 'test' // } // } // function mapdispatchtoprops(dispatch) { // return bindactioncreators({ fetchprofileifexists }, dispatch) // } app = connect(state => ({}), null)(app); export default app; //export default connect(mapstatetoprops, mapdispatchtoprops)(app)
routes.js
import react "react" import { route, indexroute } "react-router" import app "./containers/app" import emailpage "./containers/emailpage" import homepage "./containers/homepage" import occupationbranchpage "./containers/occupationbranchpage" import occupationgrouppage "./containers/occupationgrouppage" import occupationstatuspage "./containers/occupationstatuspage" import pendingmemberpage "./containers/pendingmemberpage" import personalpage "./containers/personalpage" import thankyoupage "./containers/thankyoupage" import verificationcallpage "./containers/verificationcallpage" import verificationdmdcpage "./containers/verificationdmdcpage" import verificationdocumentpage "./containers/verificationdocumentpage" import verificationemailpage "./containers/verificationemailpage" import verificationoptionspage "./containers/verificationoptionspage" export default ( <route path="/" component={app}> <indexroute component={homepage} /> <route path="/email" component={emailpage} /> <route path="/occupation-group" component={occupationgrouppage} /> <route path="/occupation-branch" component={occupationbranchpage} /> <route path="/occupation-status" component={occupationstatuspage} /> <route path="/pending-member" component={pendingmemberpage} /> <route path="/personal" component={personalpage} /> <route path="/thank-you" component={thankyoupage} /> <route path="/verification-call" component={verificationcallpage} /> <route path="/verification-dmdc" component={verificationdmdcpage} /> <route path="/verification-document" component={verificationdocumentpage} /> <route path="/verification-email" component={verificationemailpage} /> <route path="/verification-options" component={verificationoptionspage} /> </route> ) // <route path="/example/:login/:name" component={repopage} /> // <route path="/example/:login" component={userpage} />
homepage.js
import react, { component, proptypes } 'react' import { connect } 'react-redux' import { link } 'react-router' // import facebooklogin '../components/facebooklogin' class homepage extends component { constructor(props) { super(props) } componentdidmount() { //console.log('homepage componentdidmount', '\n', 'props', this.props, '\n', 'state', this.state); } componentwillunmount() { alert('unmounting') } routerwillleave(nextlocation) { console.log('homepage routerwillleave state', this.state, 'nextlocation', nextlocation) } render() { return ( <div classname='row'> <h2>welcome</h2> <link to='email' classname='btn btn-lg btn-success'>email</link> {/* <facebooklogin /> */} </div> ); } } function mapstatetoprops(state, ownprops) { // const { login } = ownprops.params // const { // pagination: { starredbyuser }, // entities: { users, repos } // } = state return { // login, // user: users[login] } } export default connect(mapstatetoprops, { })(homepage)
you don't need access store props or context. right way use connect()
function/decorator.
provider component top component, other child containers should use connect full state store or parts of it.
const mapstatetoprops = (state) => ({ thiswillbeaproperty: state.somedata, }); export default connect(mapstatetoprops)(component);
mapstatetoprops
function need, receives full state object store, , can select parts want pass prop wrapped component. example in case, component
receive thiswillbeaproperty
value state.somedata
Comments
Post a Comment