簡體   English   中英

調度動作時未調用redux connect mapStateToProps

[英]redux connect mapStateToProps not called when action is dispatched

解決方案(更新):

我以為任何動作都會導致react-redux-connect調用mapState函數,但是當一個動作什么都沒有改變時,事實並非如此。

我有一個localStorage模塊,該模塊可以調度操作,但不更改狀態,相反,您會寫入localStorage。 該模塊具有在容器中使用的選擇器,但是直到狀態實際更改時它們才被調用,因此,只有在分派了另一個更改狀態的操作之后,UI才能正確顯示。

問題

當我將商店放在窗口( window.store=store )上時,在mapStateToProps中添加console.log,然后在控制台中分派一個動作: store.dispatch({type:'some action'})然后是控制台。 mapStateToProps的日志不顯示。

我確實記住了結果,但是應該調用mapStateToProps, 請參見此處

完整的代碼在這里 ,運行示例在這里 (您可以單擊屏幕右下角的“控制台”鏈接打開控制台)。

的package.json

store.js:

import { createStore } from 'redux';
export default (initialState, reducer) => {
  const store = createStore(
    reducer,
    initialState,
    window.__REDUX_DEVTOOLS_EXTENSION__ &&
      window.__REDUX_DEVTOOLS_EXTENSION__()
  );
  window.store = store;
  return store;
};

app.js

import React from 'react';
import { connect } from 'react-redux';
import './App.css';
import createStore from './store';
import { Provider } from 'react-redux';
import initCounter from './components/Counter';
import {
  createWrapper,
  memoize,
} from './components/@common';
const COUNTER = 'COUNTER';
const selectCounterState = state => state.myCounter;
const counter = initCounter({
  actionWrapper: createWrapper(COUNTER, 'counter1'),
  selectors: { myState: selectCounterState },
  connect,
  memoize,
});
const initialState = {
  myCounter: counter.initialState,
};
const reducer = (state = initialState, action) => {
  if (action.emittedBy === COUNTER) {
    return {
      ...state,
      myCounter: counter.reducer(
        selectCounterState(state),
        action.payload
      ),
    };
  }
  return state;
};
const store = createStore(initialState, reducer);
const Counter = counter.container;
const App = () => (
  <Provider store={store}>
    <Counter id="counter1" parentId={[]} />
  </Provider>
);

export default App;

組件/計數器/索引:

import component from './component';
const INCREASE = 'INCREASE';
const reducer = (state, action) => {
  if (action.type === INCREASE) {
    return { ...state, count: state.count + 1 };
  }
  return state;
};
const makeState = memoize =>
  memoize((id, parentId, { count }) => ({
    id: parentId.concat(id),
    parentId,
    count,
  }));
const mapStateToProps = ({ myState }, memoize) => () => {
  const newState = makeState(memoize);
  return (state, ownProps) =>
    console.log('in map state to props', new Date()) ||
    newState(
      ownProps.id,
      ownProps.parentId,
      myState(state)
    );
};

export default ({
  actionWrapper,
  selectors,
  connect,
  memoize,
}) => {
  const actions = {
    increase: ({ id }) =>
      actionWrapper({
        type: INCREASE,
        id,
      }),
  };
  const container = connect(
    mapStateToProps(selectors, memoize),
    actions
  )(component);
  return {
    container,
    reducer,
    initialState: { count: 0 },
  };
};

組件/計數器/ component.js:

import React from 'react';

export default props => (
  <div>
    <button onClick={() => props.increase(props)}>
      add
    </button>
    {props.count}
  </div>
);

您的示例代碼筆工作得很好,您只需觸發一個超出頂級警衛並且具有預期結構的操作即可,以免引起任何后續錯誤:

將其發布到您的Codepen控制台中:

store.dispatch({emittedBy: "COUNTER", type: "COUNTER -> INCREASE", id: "counter1", payload: {type: "INCREASE", id: ["counter1"]}})

造成此問題的原因是,我有一個localStorage模塊,該模塊執行調度操作,但未更改狀態,而是將其寫入localStorage。

該模塊具有選擇器,這些選擇器將獲取正確的數據,並且容器將使用它們來構建正確的狀態,但是由於分派的操作並未更改redux存儲中的狀態,因此react-redux會跳過調用我的mapState函數(可能在Provider中記住狀態) )。

解決方案是讓根縮減器返回新的狀態引用{...state}以便任何操作都會導致mapState函數被調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM