Redux store not connected

我怕爱的太早我们不能终老 提交于 2019-12-20 07:44:48

问题


I am developing a Reactjs web application from scratch and encountered a tricky situation which i need help with. Whenever i navigate away from a particular url and navigate back, my redux store does not seem to be connected.

routes.js

const RouteList = () => (
  <main>
    <Switch>
      <Route path="/abc/" exact component={withRouter(HomePage)} />
      <Route path="/abc/xyz" exact component={withRouter(XYZPage)} />
      <Redirect from="/" to="/abc/" />
      <Route component={Error} />
     </Switch>
   </main>
);
export default RouteList;

App.js

class  App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  render () {
    return (
      <Router history={browserHistory}>
        <div>
          <Header />
          <RouteList />
          <Footer />
        </div>
      </Router>
    );
  }
}

export default App;

Header.js

const Header = () => {
  return (
    <Navbar expand="md">
      <NavbarBrand tag={NavLink} to="/">
        <img src={brandImage} style={{marginRight: "0", width: "40px", height: "40px"}} /><strong style={{color: "#457B9D"}} >Datum</strong>
      </NavbarBrand>

      <Nav className="mr-auto" navbar>
        <NavItem>
          <NavLink className="nav-link" to={"/abc/xyz"} >XYZ</NavLink>
        </NavItem>
      </Nav>
    </Navbar>
  );
};

export default withRouter(Header);

When i hit the NavLink which will take me to url: /"abc/xyz", it will take me to XYZPage.js

XYZPage.js

class XYZPage extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      activeTab: "1"
    };

    this.toggle = this.toggle.bind(this);
  }

  toggle(tab) {
    if (this.state.activeTab !== tab) {
      this.setState({
        activeTab: tab
      });
    }
  }
  render () {
    return (
      <main>
        <div className="container-fluid pt-3">
          <Nav tabs>
            <NavItem>
              <NavLink
                className={classnames({active: this.state.activeTab === "1"})}
                onClick={() => {this.toggle("1"); }} >
                AAA
              </NavLink>
            </NavItem>
            <NavItem>
              <NavLink
                className={classnames({active: this.state.activeTab === "2"})}
                onClick={() => {this.toggle("2"); }} >
                BBB
              </NavLink>
            </NavItem>
            <NavItem>
              <NavLink
                className={classnames({active: this.state.activeTab === "3"})}
                onClick={() => {this.toggle("3"); }} >
                CCC
              </NavLink>
            </NavItem>
          </Nav>
          <TabContent activeTab={this.state.activeTab}>
            <TabPane tabId="1">
              <Row>
                <AAAPAge/>
              </Row>
            </TabPane>
            <TabPane tabId="2">
              <Row>
                <BBBPage/>
              </Row>
            </TabPane>
            <TabPane tabId="3">
              <Row>
                <CCCPage/>
              </Row>
            </TabPane>
          </TabContent>
        </div>
      </main>
    );
  }
}

export default withRouter(XYZPage);

Each of the AAAPage, BBBPage & CCCPage are components which needs to have some pre-populated dropdowns which i declared in my index.js below:

index.js

const store = configureStore();
store.dispatch(loadAAA());
store.dispatch(loadBBB());
store.dispatch(loadCCC());

render((
  <Provider store={store}>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </Provider>
), document.getElementById('app'));

loadAAA, loadBBB & loadCCC are all thunks

The configureStore() method is as such:

export default function configureStore(initialState) {
  return createStore(
    rootReducer,
    initialState,
    composeWithDevTools(
      applyMiddleware(thunk, reduxImmutableStateInvariant()),
    )
  );
}

To shorten this post i give a sample of my AAAPage as the others are of similar structure:

AAAPage.js:

class AAAPage extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.state = {...};
  }

  componentWillReceiveProps(nextProps) {...}

  render() {
    [...]
    return (
      <Container fluid>
        <Row>
          <AAAInputForm
            // Data from Store is passed here 
          />
        </Row>
        {ChildComponent}
      </Container>
    );
  }
}

AAAPage.propTypes = {
  DATA: PropTypes.array
};

function mapStateToProps(state, ownProps) {
  let DATA = [];
  if (state.AAAReducer.length > 0) {
    DATA = state.AAAReducer;
  }

  return {
    DATA: DATA
  };
}

export default withRouter(connect(mapStateToProps)(AAAPage));

AAAReducer.js:

export default function AAAReducer(state=initialState.AAAList, action) {
  switch(action.type) {
    case types.LOAD_AAA_SUCCESS:
      return action.AAAList;

    default:
      return state;
  }
}

AAAAction.js:

export function loadAAASuccess(AAAList) {
  return {
    type: types.LOAD_AAA_SUCCESS,
    AAAList: AAAlList
  };
}

// thunk
export function loadAAA() {
  // A thunk will always return a function that accepts a dispatch
  return function(dispatch) {
    return apiCall("ALL").then(response => {
      dispatch(loadAAASuccess(response.data.AAA));
    }).catch(error => {
      throw(error);
    });
  };
}

initialState.js:

export default {
  AAAList: [],
  BBBList: [],
  CCCList: []
};

At this point i believe i provided enough background to my code. I followed tutorials when designing this redux store and I am not sure why when i navigate from "/abc/xyz" to "/abc" and back, or when i navigate to "/abc/xyz" from "/abc", my stores are empty although i called the loadAAA() method at my index.js. All the other pages are affected as well. However, when i hit "/abc/xyz" directly, my stores are connected and my dropdowns are populated. What is happening? Is it because of my lifecycle methods?

I am using react v15.6.2, redux v3.7.2 & redux-thunk v2.3.0.

Thanks for the guidance.


回答1:


You only call loadAAA at the top level of index.js, which only executes once when your page loads. If you want to dispatch it every time your XYZPage page renders, put in XYZ's componentDidMount




回答2:


@AKJ - @Andy Ray said it correctly, but I'll like to add that componentDidMount is the best place to load async calls, as it is called after render and about Store redux store keeps data until you refresh the page after refresh redux store is reinitialized, if you need store the data after refresh try redux-persist



来源:https://stackoverflow.com/questions/54778492/redux-store-not-connected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!