Redux 存储未连接 [英] Redux store not connected

查看:44
本文介绍了Redux 存储未连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

routes.js

const RouteList = () =>(<主要><开关><Route path="/abc/" 精确组件={withRouter(HomePage)}/><Route path="/abc/xyz" 精确组件={withRouter(XYZPage)}/><Redirect from="/" to="/abc/"/><路由组件={Error}/></开关></main>);导出默认路由列表;

App.js

class App 扩展 React.Component {构造函数(道具){超级(道具);this.state = {};}使成为 () {返回 (<路由器历史={browserHistory}><div><标题/><路由列表/><页脚/>

</路由器>);}}导出默认应用程序;

Header.js

const Header = () =>{返回 (<Navbar expand="md"><NavbarBrand tag={NavLink} to="/"><img src={brandImage} style={{marginRight: "0", width: "40px", height: "40px"}}/><strong style={{color: "#457B9D"}} >;数据</NavbarBrand><Nav className="mr-auto" 导航栏><导航项目><NavLink className="nav-link" to={"/abc/xyz"} >XYZ</NavLink></NavItem></导航></导航栏>);};导出默认 withRouter(Header);

当我点击 NavLink 时,它会带我到 url:/"abc/xyz",它会带我到 XYZPage.js

XYZPage.js

class XYZPage 扩展 React.Component {构造函数(道具,上下文){超级(道具,上下文);this.state = {活动标签:1"};this.toggle = this.toggle.bind(this);}切换(标签){if (this.state.activeTab !== tab) {this.setState({activeTab:选项卡});}}使成为 () {返回 (<主要><div className="container-fluid pt-3"><导航标签><导航项目><导航链接className={classnames({active: this.state.activeTab === "1"})}onClick={() =>{this.toggle("1");}} >AAA</NavLink></NavItem><导航项目><导航链接className={classnames({active: this.state.activeTab === "2"})}onClick={() =>{this.toggle("2");}} >BBB</NavLink></NavItem><导航项目><导航链接className={classnames({active: this.state.activeTab === "3"})}onClick={() =>{this.toggle("3");}} >CCC</NavLink></NavItem></导航><TabContent activeTab={this.state.activeTab}><TabPane tabId="1"><行><AAAPage/></行></TabPane><TabPane tabId="2"><行><BBBPage/></行></TabPane><TabPane tabId="3"><行><CCCPage/></行></TabPane></TabContent>

</main>);}}导出默认 withRouter(XYZPage);

AAAPage, BBBPage &CCCPage 是需要预先填充下拉列表的组件,我在下面的 index.js 中声明:

index.js

const store = configureStore();store.dispatch(loadAAA());store.dispatch(loadBBB());store.dispatch(loadCCC());使成为((<提供者商店={商店}><浏览器路由器><应用程序/></BrowserRouter></提供者>), document.getElementById('app'));

loadAAA, loadBBB &loadCCC 都是 thunk

configureStore() 方法是这样的:

导出默认函数 configureStore(initialState) {返回创建商店(根减速器,初始状态,composeWithDevTools(applyMiddleware(thunk, reduxImmutableStateInvariant()),));}

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

AAAPage.js:

class AAAPage extends React.Component {构造函数(道具,上下文){超级(道具,上下文);this.state = {...};}componentWillReceiveProps(nextProps) {...}使成为() {[...]返回 (<容器流体><行><AAA输入表单//来自Store的数据传递到这里/></行>{子组件}</容器>);}}AAAPage.propTypes = {数据:PropTypes.array};函数 mapStateToProps(state, ownProps) {让数据 = [];如果(state.AAAReducer.length > 0){数据 = state.AAAReducer;}返回 {数据:数据};}导出默认 withRouter(connect(mapStateToProps)(AAAPage));

AAAReducer.js:

导出默认函数 AAAReducer(state=initialState.AAAList, action) {开关(动作.类型){案例类型.LOAD_AAA_SUCCESS:返回 action.AAAList;默认:返回状态;}}

AAAAction.js:

导出函数 loadAAASuccess(AAAList) {返回 {类型:types.LOAD_AAA_SUCCESS,AAAList: AAAlList};}//重击导出函数 loadAAA() {//thunk 总是会返回一个接受调度的函数返回函数(调度){返回 apiCall("ALL").then(response => {调度(loadAAASuccess(response.data.AAA));}).catch(错误=>{抛出(错误);});};}

initialState.js:

出口默认{AAAList: [],BBBList: [],CCC列表:[]};

在这一点上,我相信我为我的代码提供了足够的背景知识.我在设计这个 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.

谢谢指导.

解决方案

你只在 index.js 的顶层调用 loadAAA,当你的页面加载.如果您想在每次 XYZPage 页面呈现时发送它,请放入 XYZ 的 componentDidMount

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.

解决方案

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

这篇关于Redux 存储未连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆