我有一个我认为相当标准的React Redux设置,其中混合了一些持久性。
app.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import AppRouter from './routers/AppRouter';
import configureStore from './store/configureStore';
import config from 'cgConfig';
const { store, persistor } = configureStore();
const jsx = (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<AppRouter />
</PersistGate>
</Provider>
);
ReactDOM.render(jsx, document.getElementById(config.constants.element.rootId));
configStore.js
import {
createStore,
combineReducers
} from 'redux';
import {
persistStore,
persistReducer
} from 'redux-persist';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
import storage from 'redux-persist/lib/storage';
import config from 'cgConfig';
//...import reducers...
export default () => {
const persistConfig = {
key: 'root',
storage,
stateReconciler: autoMergeLevel2
};
let rootReducer = combineReducers({
//...all of my reducers...
});
let store = undefined;
let pr = persistReducer(persistConfig, rootReducer);
if (config.env.includeReduxDevTools) {
store = createStore(
pr,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
} else {
store = createStore(pr);
}
let persistor = persistStore(store);
return {
store,
persistor
};
};
然而,有一件事有点非常规,那就是我需要在react组件的上下文之外更新存储。据我所知(例如(,这应该不会太难实现。只需调用configureStore()
即可获取存储并运行store.dispatch(action)
。问题是,我一直在获取存储的初始状态(IE为空(,这与我在登录等过程中已经设置的状态不同。因此,当我运行dispatch
时,错误的状态正在更新。
不确定我做错了什么,如果有任何帮助,我将不胜感激。
编辑以回答Uma关于路由器外观的问题:
首先是一些上下文。我正在开发的网站基本上会生成类似于图形的形状。这些形状可以在从各种来源(如上下文菜单和工具栏(中选择后进行操作。正是在这个变化事件的背景下,我正在努力。
当进行更改时,所选项目的信息以及需要更改的内容将被发送到一个通用函数,该函数将确定使用哪个减少程序/操作来更新Redux存储。我所有的减速器都遵循相同的模式,看起来像这样:
const reducerInitialState = {};
const setSomeProperty= (state, action) => {
let newState = { ...state };
newState.some_property = action.some_update;
return newState;
};
export default (state = reducerInitialState, action) => {
switch (action.type) {
case 'UPDATE_SOME_PROPERTY':
return setSomeProperty(state, action);
case 'LOG_OUT':
return { ...reducerInitialState };
default:
return state;
}
};
完整性行动:
export const setSomeProperty = update_data => ({
type: 'UPDATE_SOME_PROPERTY',
some_update: update_data
});
我的通用函数看起来像这样:
import configureStore from './store/configureStore';
import { setSomeProperty} from './actions/SomeAction';
import API from './utilities/API';
export default async ({ newValue, selectedShape }) => {
if (!newValue || !selectedShape)
throw "Cannot update the server with missing parameters.";
await API()
.post(
`/api/update-shape`,
{
newValue,
shape: selectedShape
}
)
.then(response => {
updateValue({ selectedShape, newValue });
})
.catch(error => {
// handle error
});
}
const getAction = ({ shape }) => {
switch (shape.type) {
case 0:
return setSomeProperty;
default:
throw `Invalid type of ${shape.type} attempting to update.`;
}
}
const updateValue = ({ selectedShape, newValue }) => {
const action = getAction({ shape: selectedShape })
const { store } = configureStore();
store.dispatch(action(newValue))
}
注:API是Axios的包装器。
自从昨天发布这篇文章以来,我读到创建第二个商店,就像我用const { store } = configureStore();
做的那样,我的问题之一在于React/Redux不能有两个。我还意识到,问题很可能与我的还原器中的初始状态有关,以某种方式使用configureStore()
不会将实际状态发送给还原器,因此当我使用console.log(store.getState());
查看它们时,我的所有还原器都显示了它们的初始状态。如果这是真的,至少我知道问题所在,这已经成功了一半,但我不确定如何继续,因为我已经尝试过重新水合configureStore()
的状态,但似乎没有任何效果
据我所知,在一个奇怪的循环中,你调用了一个动作setSomeProperty
,然后它将你带到reducer,在reducer中,你再次调用该setSomeProperty
动作。
在减速器中,我希望看到这样的东西:
export default (state = reducerInitialState, action) => {
switch (action.type) {
case 'UPDATE_SOME_PROPERTY':
return {
...state, // preserve already set state properties if needed
some_update: action.some_update
}
case 'LOG_OUT':
return { ...reducerInitialState };
default:
return state;
}
};