Решение (обновлено):
Я думал, любое действие приведет к тому, что 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>
);