【问题标题】:Redux store not connectedRedux 商店未连接
【发布时间】:2019-07-13 16:18:37
【问题描述】:

我正在从头开始开发 Reactjs Web 应用程序,遇到了一个需要帮助的棘手情况。每当我离开特定的 url 并返回时,我的 redux 商店似乎没有连接。

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);

当我点击导航链接时,它将带我到 url:/"abc/xyz",它会带我到 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);

每个 AAAPage、BBBPage 和 CCCPage 都是需要有一些预先填充的下拉列表的组件,我在下面的 index.js 中声明了这些下拉列表:

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 都是 thunk

configureStore()方法是这样的:

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

为了缩短这篇文章,我提供了一个我的 AAAPage 的示例,因为其他页面的结构相似:

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: []
};

在这一点上,我相信我为我的代码提供了足够的背景。我在设计这个 redux 商店时遵循了教程,但我不知道为什么当我从“/abc/xyz”导航到“/abc”并返回时,或者当我从“/abc”导航到“/abc/xyz”时,我的尽管我在 index.js 中调用了 loadAAA() 方法,但商店是空的。所有其他页面也会受到影响。但是,当我直接点击“/abc/xyz”时,我的商店已连接并且我的下拉列表已填充。怎么了?是因为我的生命周期方法吗?

我正在使用 react v15.6.2、redux v3.7.2 和 redux-thunk v2.3.0。

感谢您的指导。

【问题讨论】:

    标签: javascript reactjs react-redux react-router-v4 redux-thunk


    【解决方案1】:

    您只能在index.js 的顶层调用loadAAA,它只会在您的页面加载时执行一次。如果您想在每次 XYZPage 页面呈现时调度它,请输入 XYZ 的 componentDidMount

    【讨论】:

    • 好的,会这样做,但需要这样做的原因是什么? redux store 不记得状态还是我误解了 redux store 的工作原理?
    【解决方案2】:

    @AKJ - @Andy Ray 说得对,但我想补充一点,componentDidMount 是加载 async 调用的最佳位置,因为它是在渲染之后调用的,并且关于 Store redux 存储保留数据直到刷新 redux store 重新初始化后刷新页面,如果需要在刷新后存储数据尝试redux-persist

    【讨论】:

    • 如果是这种情况,那么我们是否建议 mapStateToProps 仅适用于非异步调用的状态?我一直认为,当我进行调度调用时,只要会话处于活动状态,商店就会记住数据。当我从一个页面导航到另一个页面时,我没想到商店会忘记它的状态。如前所述,我遵循了 cory-house 的复数教程,在该教程中,他没有使用 componentDidMount 来调用从模拟同步调用中获取的一些数据。他只是在 index.js 上为 store 补水并通过 传递它。你能进一步启发我吗?
    • React 允许我们以多种方式解决问题,在您的情况下,您的商店是否记得?您可以使用redux-dev-tools 进行检查,只需保持您的开发工具打开并在从另一个页面导航时检查
    • 当我打开dev-tool redux时,我的商店还记得状态
    • 如果您的商店记得这意味着您需要处理生命周期方法来呈现数据屏幕。
    • 我可以知道是哪种生命周期方法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-02
    • 2018-06-13
    • 2020-01-14
    • 1970-01-01
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    相关资源
    最近更新 更多