redux connect mapStateToProps не вызывается при отправке действия - PullRequest
0 голосов
/ 10 мая 2019

Решение (обновлено):

Я думал, любое действие приведет к тому, что Reaction-Redux-Connect вызовет функции mapState, но когда действие ничего не меняет, это не так.

У меня есть модуль localStorage, который отправляет действия, но не изменяет состояние, вместо этого вы будете писать в localStorage. В модуле есть селекторы, которые используются в контейнерах, но они не будут вызываться до тех пор, пока состояние фактически не изменится, поэтому пользовательский интерфейс будет отображаться правильно только после того, как было отправлено другое действие, которое изменит состояние.

Задача

Когда я помещаю хранилище в окно (window.store=store), добавьте console.log в mapStateToProps, затем в консоли отправляю действие: store.dispatch({type:'some action'}) тогда console.log в 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>
);

Ответы [ 2 ]

1 голос
/ 10 мая 2019

Ваш пример codepen работает просто отлично, вам просто нужно вызвать действие, которое проходит мимо вашего верхнего уровня защиты и имеет ожидаемую структуру, чтобы не вызывать каких-либо последующих ошибок:

Опубликовать это в консоливашего кода:

store.dispatch({emittedBy: "COUNTER", type: "COUNTER -> INCREASE", id: "counter1", payload: {type: "INCREASE", id: ["counter1"]}})
0 голосов
/ 10 мая 2019

Эта проблема была вызвана тем, что у меня был модуль localStorage, который выполнял действия по отправке, но не изменял состояние, вместо этого он записывал в localStorage.

В модуле были селекторы, которые получали бы правильные данные, и контейнеры использовали их для построения правильного состояния, но так как отправленное действие не изменило состояние в хранилище redux, реакция-redux пропустит вызов функций mapState (возможно, запоминание состояние в провайдере).

Решение состоит в том, чтобы разрешить корневому редуктору возвращать новую ссылку на состояние {...state}, чтобы любое действие вызывало вызов функций mapState.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...