Redux 스토어 상태를 리셋하는 방법
리덕스
스토어를 초기 상태로 리셋하려면 어떻게 해야 하나요?
가 두의 사용자 계정(예: 2개의 사용자 계정)을 있다고해 보겠습니다.u1
★★★★★★★★★★★★★★★★★」u2
를 참조해 주세요.
이치노
" "
u1
앱에 로그인해서 뭔가를 하기 때문에 스토어에 데이터를 캐시합니다." "
u1
로그아웃 합니다." "
u2
브라우저를 새로 고치지 않고 앱에 로그인합니다.
는 " "와 .u1
청소하고 싶습니다.
첫 번째 사용자가 로그아웃할 때 Redux 저장소를 초기 상태로 재설정하려면 어떻게 해야 합니까?
이를 위한 한 가지 방법은 응용 프로그램에 루트 리덕터를 쓰는 것입니다.
, 를, 에된 리덕터에 합니다.combineReducers()
수신할 마다, 수신할 수 있습니다USER_LOGOUT
초기 .action은 원래 상태로 되돌립니다.
예를 들어 루트 리덕터가 다음과 같은 경우:
const rootReducer = combineReducers({
/* your app’s top-level reducers */
})
해서 이름을 수 요.appReducer
rootReducer
★★★★
const appReducer = combineReducers({
/* your app’s top-level reducers */
})
const rootReducer = (state, action) => {
return appReducer(state, action)
}
, 이제 것을 주면 .rootReducer
로 USER_LOGOUT
액션.아시다시피, 리듀서는 다음과 같이 호출되면 초기 상태를 반환해야 합니다.undefined
첫 번째 논쟁으로 삼을 수 있습니다. 이 된 것을 해 볼까요?state
을 리리에 .appReducer
:
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
return appReducer(undefined, action)
}
return appReducer(state, action)
}
이제 제, now, 언, 지, nowUSER_LOGOUT
모든 감속기가 새로 초기화됩니다.때 수도 . ,, 크, 른, 른, 른, 른, 른, 른, 른, 른, 른, 른, 른, 른, 른, 른, 른을 수 있기 때문입니다.action.type
뿐만 아니라.
다시 한 번 강조하자면, 완전한 새 코드는 다음과 같습니다.
const appReducer = combineReducers({
/* your app’s top-level reducers */
})
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
return appReducer(undefined, action)
}
return appReducer(state, action)
}
redux-persist를 사용하는 경우 스토리지를 청소해야 할 수도 있습니다.Redux-persist는 스토리지 엔진에 상태 복사본을 보관하며, 상태 복사본은 새로 고침 시 그곳에서 로드됩니다.
먼저 적절한 스토리지 엔진을 Import한 후 다음 상태로 설정하기 전에 상태를 해석해야 합니다.undefined
각 스토리지 상태 키를 청소합니다.
const rootReducer = (state, action) => {
if (action.type === SIGNOUT_REQUEST) {
// for all keys defined in your persistConfig(s)
storage.removeItem('persist:root')
// storage.removeItem('persist:otherKey')
return appReducer(undefined, action);
}
return appReducer(state, action);
};
Dan Abramov의 답변은 정확합니다.단, 이 접근방식과 함께 react-router-redux 패키지를 사용할 때 이상한 문제가 발생했습니다.
를 「(으)」로 하지 않는 이었습니다.undefined
현재의 라우팅 리듀서를 사용합니다. 이 아래의 합니다.
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
const { routing } = state
state = { routing }
}
return appReducer(state, action)
}
액션을 정의합니다.
const RESET_ACTION = {
type: "RESET"
}
으로 각 에서는 리듀서(Reduceer)를 사용하고 합니다.에서switch
★★★★★★★★★★★★★★★★★」if-else
각 리듀서를 통해 여러 작업을 처리할 수 있습니다.는 그 .switch
.
const INITIAL_STATE = {
loggedIn: true
}
const randomReducer = (state=INITIAL_STATE, action) {
switch(action.type) {
case 'SOME_ACTION_TYPE':
//do something with it
case "RESET":
return INITIAL_STATE; //Always return the initial state
default:
return state;
}
}
부르면 항상 요.RESET
stateaction, reducer로 스토어를 합니다.
로그아웃의 경우 다음과 같은 처리를 할 수 있습니다.
const logoutHandler = () => {
store.dispatch(RESET_ACTION)
// Also the custom logic like for the rest of the logout handler
}
사용자가 로그인할 때마다 브라우저를 새로 고치지 않습니다.스토어는 항상 기본값이 됩니다.
store.dispatch(RESET_ACTION)
목적을 위한 입니다.그 목적을 위한 액션 크리에이터가 있을 가능성이 높습니다. 더 좋은 은 씬씬 a a a a a a a a a a a a a a a a a a a a a a a a a a a a가 있는 입니다.LOGOUT_ACTION
this 를 디스패치하면LOGOUT_ACTION
커스텀 미들웨어는 Redx-Saga 또는 Redx-Thunk를 사용하여 이 액션을 대행 수신할 수 있습니다.다만, 어느 쪽이든, 다른 액션 「RESET」를 디스패치 할 수 있습니다.이렇게 하면 스토어 로그아웃 및 리셋이 동기화되어 스토어가 다른 사용자 로그인을 준비할 수 있습니다.
Dan Abramov의 답변에 대한 간단한 답변입니다.
const rootReducer = combineReducers({
auth: authReducer,
...formReducers,
routing
});
export default (state, action) =>
rootReducer(action.type === 'USER_LOGOUT' ? undefined : state, action);
Redux Toolkit 및/또는 Typescript 사용:
const appReducer = combineReducers({
/* your app’s top-level reducers */
});
const rootReducer = (
state: ReturnType<typeof appReducer>,
action: AnyAction
) => {
/* if you are using RTK, you can import your action and use it's type property instead of the literal definition of the action */
if (action.type === logout.type) {
return appReducer(undefined, { type: undefined });
}
return appReducer(state, action);
};
const reducer = (state = initialState, { type, payload }) => {
switch (type) {
case RESET_STORE: {
state = initialState
}
break
}
return state
}
또한 초기 저장소로 재설정하려는 모든 또는 일부 환원 장치가 처리하는 작업을 실행할 수도 있습니다.한 번의 작업으로 전체 상태로 리셋하거나 사용자에게 적합한 일부 상태로 리셋할 수 있습니다.나는 이것이 이것을 하는 가장 간단하고 통제하기 쉬운 방법이라고 믿는다.
에서 사용자를 로그아웃할 때 인 상태 "cookie")를입니다.localStorage
,IndexedDB
,Web SQL
리프레시)를 사용하여 를 새로 고칩니다window.location.reload()
로 또는 수 window
등에서는, DOM 하는 것만이, 한 방법입니다모든 영속적인 상태를 삭제하고 브라우저를 새로 고치는 것이 이전 사용자의 정보가 다음 사용자에게 유출되지 않도록 하는 유일한 방법입니다.
(물론 공유 컴퓨터 사용자라면 '프라이빗 브라우징' 모드를 사용하거나 브라우저 창을 직접 닫거나 '브라우징 데이터 클리어' 기능 등을 사용해야 하지만 개발자로서 모두가 항상 부지런할 것이라고는 기대할 수 없습니다.)
Redx를 사용하여 Redx를 합니다.initialState
(예: 모든 리듀서)에 포함되어 있습니다.{ user: { name, email }}
네스트에 이된 속성 "예: "가" "예: "가" "예: "가" "이 경우")에서 되는 것을 state.user.email
user is undefined
(「」 「」 「」)
const appReducer = combineReducers({
tabs,
user
})
const initialState = appReducer({}, {})
const rootReducer = (state, action) => {
if (action.type === 'LOG_OUT') {
state = initialState
}
return appReducer(state, action)
}
NGRX4 업데이트
NGRX 4로 이행하는 경우 이행가이드에서 다음 사항을 알 수 있습니다.rootreducer
이 듀를 the the the the 로 되었습니다.ActionReducerMap
이 를 재설정하는것이 수 .처음에, 이 새로운 방식의 일은 국가를 다시 세우는 것을 어렵게 만들 수 있다.이것은 사실 간단하지만, 이것을 하는 방법은 바뀌었습니다.
이 솔루션은 NGRX4 Github 문서의 meta-reducers API 섹션에서 영감을 받았습니다.
NGRX의 NGRX를 하여 이렇게 .ActionReducerMap
★★★★
//index.reducer.ts
export const reducers: ActionReducerMap<State> = {
auth: fromAuth.reducer,
layout: fromLayout.reducer,
users: fromUsers.reducer,
networks: fromNetworks.reducer,
routingDisplay: fromRoutingDisplay.reducer,
routing: fromRouting.reducer,
routes: fromRoutes.reducer,
routesFilter: fromRoutesFilter.reducer,
params: fromParams.reducer
}
그럼 에는 '내부'에서해 보겠습니다.app.module
//app.module.ts
import { IndexReducer } from './index.reducer';
import { StoreModule, ActionReducer, MetaReducer } from '@ngrx/store';
...
export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
return function(state, action) {
switch (action.type) {
case fromAuth.LOGOUT:
console.log("logout action");
state = undefined;
}
return reducer(state, action);
}
}
export const metaReducers: MetaReducer<any>[] = [debug];
@NgModule({
imports: [
...
StoreModule.forRoot(reducers, { metaReducers}),
...
]
})
export class AppModule { }
이는 기본적으로 NGRX 4에서도 같은 효과를 얻을 수 있는 하나의 방법입니다.
Dan Abramov의 답변에 따라 작성된 타이프스크립트를 사용할 때의 회피책(리듀스 타이핑은 합격할 수 없음)undefined
첫 번째 인수로 reducer하기 때문에 초기 루트 상태를 상수로 캐시합니다).
// store
export const store: Store<IStoreState> = createStore(
rootReducer,
storeEnhacer,
)
export const initialRootState = {
...store.getState(),
}
// root reducer
const appReducer = combineReducers<IStoreState>(reducers)
export const rootReducer = (state: IStoreState, action: IAction<any>) => {
if (action.type === "USER_LOGOUT") {
return appReducer(initialRootState, action)
}
return appReducer(state, action)
}
// auth service
class Auth {
...
logout() {
store.dispatch({type: "USER_LOGOUT"})
}
}
로그아웃 링크를 클리어하고 페이지를 갱신하기만 하면 됩니다.스토어에 추가 코드는 필요 없습니다.상태를 완전히 재설정하려면 페이지 새로 고침을 단순하고 쉽게 반복할 수 있습니다.
redux-actions를 사용하는 경우 HOF(Higher Order Function)를 사용한 간단한 회피책을 소개합니다.handleActions
.
import { handleActions } from 'redux-actions';
export function handleActionsEx(reducer, initialState) {
const enhancedReducer = {
...reducer,
RESET: () => initialState
};
return handleActions(enhancedReducer, initialState);
}
다음에 and고 and and를 사용합니다.handleActionsEx
의 handleActions
리듀서를 다룰 수 있습니다.
댄의 답변은 이 문제에 대한 좋은 아이디어를 주지만 잘 풀리지 않았다.왜냐하면 나는 이 문제를 사용하고 있기 때문이다.redux-persist
.
「 」와 함께 redux-persist
지나치다undefined
지속 동작을 트리거하지 때문에 것을 알았습니다(내 경우 Native, 즉 내 NativeAsyncStorage
를 참조해 주세요.
await AsyncStorage.removeItem('persist:root');
또는
await persistor.flush(); // or await persistor.purge();
저도 안 먹혔어요.그냥 소리만 질렀어요.(예: "뜻밖의 열쇠 _ persist..."라고 불평하는 등)
건 '다 하다'가 '다'가 '다'가 '다'가 '다'가 '다'가'가 되면 환원제가 '' 예요. 내가 원하는 건 단지 모든 개별 리듀서를 초기 상태로 되돌리는 것뿐이에요.RESET
이치노그렇게 하면 끈기가 자연스럽게 처리됩니다.위用함수)가 없는 것은 분명합니다.handleActionsEx
「 않습니다( 1개의 라이너에 ).RESET: () => initialState
메타프로그래밍을 너무 좋아해서 견딜 수가 없었어요.
Dan Abramov의 답변, Ryan Irilli의 답변, 그리고 Rob Moorman의 답변을 조합하여, 이 답변이 유지되는 이유를 설명합니다.router
스테이트 트리의 다른 모든 것을 초기화하면 다음과 같은 결과가 됩니다.
const rootReducer = (state, action) => appReducer(action.type === LOGOUT ? {
...appReducer({}, {}),
router: state && state.router || {}
} : state, action);
나는 상태를 정리하기 위한 행동을 만들었다.따라서 로그아웃액션 작성자를 디스패치할 때는 클리어 스테이트에도 액션을 디스패치합니다.
사용자 레코드 액션
export const clearUserRecord = () => ({
type: CLEAR_USER_RECORD
});
로그아웃 작업 생성자
export const logoutUser = () => {
return dispatch => {
dispatch(requestLogout())
dispatch(receiveLogout())
localStorage.removeItem('auth_token')
dispatch({ type: 'CLEAR_USER_RECORD' })
}
};
리듀서
const userRecords = (state = {isFetching: false,
userRecord: [], message: ''}, action) => {
switch (action.type) {
case REQUEST_USER_RECORD:
return { ...state,
isFetching: true}
case RECEIVE_USER_RECORD:
return { ...state,
isFetching: false,
userRecord: action.user_record}
case USER_RECORD_ERROR:
return { ...state,
isFetching: false,
message: action.message}
case CLEAR_USER_RECORD:
return {...state,
isFetching: false,
message: '',
userRecord: []}
default:
return state
}
};
이게 최선인지 잘 모르겠어요.
Redx가 초기 상태의 동일한 변수를 참조하지 않도록 하기 위한 나의 조치:
// write the default state as a function
const defaultOptionsState = () => ({
option1: '',
option2: 42,
});
const initialState = {
options: defaultOptionsState() // invoke it in your initial state
};
export default (state = initialState, action) => {
switch (action.type) {
case RESET_OPTIONS:
return {
...state,
options: defaultOptionsState() // invoke the default function to reset this part of the state
};
default:
return state;
}
};
수를 만들었습니다를 강화하고 Redux를 .이 컴포넌트를 사용하여 스토어를 강화하고 특정 컴포넌트를 디스패치하면 됩니다.action.type
트리거합니다.구현에 대한 생각은 Dan Abramov가 답변에서 말한 것과 동일합니다.
Github: https://github.com/wwayne/redux-reset
다음과 같은 해결책이 나에게 효과가 있었다.
메타 리듀서에 리셋 상태 기능을 추가했습니다.열쇠는 사용법이었다.
return reducer(undefined, action);
이치노 ★★★★undefined
오히려 가게의 구조가 파괴되어 오류가 발생하고 있었습니다.
/syslogers/index.ts
export function resetState(reducer: ActionReducer<State>): ActionReducer<State> {
return function (state: State, action: Action): State {
switch (action.type) {
case AuthActionTypes.Logout: {
return reducer(undefined, action);
}
default: {
return reducer(state, action);
}
}
};
}
export const metaReducers: MetaReducer<State>[] = [ resetState ];
app.disc.ts
import { StoreModule } from '@ngrx/store';
import { metaReducers, reducers } from './reducers';
@NgModule({
imports: [
StoreModule.forRoot(reducers, { metaReducers })
]
})
export class AppModule {}
댄 아브라모프의 답변이 사건을 해결하는 데 도움이 되었다.그러나, 나는 전체 상태를 클리어 할 필요가 없는 경우를 만났다.그래서 이렇게 했어요.
const combinedReducer = combineReducers({
// my reducers
});
const rootReducer = (state, action) => {
if (action.type === RESET_REDUX_STATE) {
// clear everything but keep the stuff we want to be preserved ..
delete state.something;
delete state.anotherThing;
}
return combinedReducer(state, action);
}
export default rootReducer;
@dan-abramov answer의 확장일 뿐입니다.특정 키가 리셋되지 않도록 유지해야 할 경우가 있습니다.
const retainKeys = ['appConfig'];
const rootReducer = (state, action) => {
if (action.type === 'LOGOUT_USER_SUCCESS' && state) {
state = !isEmpty(retainKeys) ? pick(state, retainKeys) : undefined;
}
return appReducer(state, action);
};
이 접근방식은 매우 옳습니다.특정 상태 "NAME"을 파기하여 다른 상태를 무시하고 유지합니다.
const rootReducer = (state, action) => {
if (action.type === 'USER_LOGOUT') {
state.NAME = undefined
}
return appReducer(state, action)
}
상태를 초기 상태로 리셋하기 위해 다음 코드를 작성했습니다.
const appReducers = (state, action) =>
combineReducers({ reducer1, reducer2, user })(
action.type === "LOGOUT" ? undefined : state,
action
);
댄 아브라모프의 답변이 내게는 잘 먹혔지만, 그것이 ESLint를 촉발시켰다.no-param-reassign
오류 - https://eslint.org/docs/rules/no-param-reassign
대신 다음과 같이 대처하고, 반드시 상태 복사본을 작성합니다(내 이해로는, Redoxy 작업입니다).
import { combineReducers } from "redux"
import { routerReducer } from "react-router-redux"
import ws from "reducers/ws"
import session from "reducers/session"
import app from "reducers/app"
const appReducer = combineReducers({
"routing": routerReducer,
ws,
session,
app
})
export default (state, action) => {
const stateCopy = action.type === "LOGOUT" ? undefined : { ...state }
return appReducer(stateCopy, action)
}
하지만 주정부의 복사본을 만드는 것이 좀 복잡할 수도 있습니다.이것은 그다지 좋은 것은 아니지만, 보다 요령 있게 읽혀지고 있습니다.
export default (state, action) => {
return appReducer(action.type === "LOGOUT" ? undefined : state, action)
}
먼저 응용 프로그램 시작 시 리듀서 상태는 새로워지고 기본 InitialState로 새로워집니다.
APP 초기 로드에 대해 호출하는 액션을 추가하여 기본 상태를 유지해야 합니다.
응용 프로그램에서 로그아웃하는 동안 기본 상태를 재할당하면 리듀서도 새 것과 동일하게 작동합니다.
메인 APP 컨테이너
componentDidMount() {
this.props.persistReducerState();
}
메인 APP 리듀서
const appReducer = combineReducers({
user: userStatusReducer,
analysis: analysisReducer,
incentives: incentivesReducer
});
let defaultState = null;
export default (state, action) => {
switch (action.type) {
case appActions.ON_APP_LOAD:
defaultState = defaultState || state;
break;
case userLoginActions.USER_LOGOUT:
state = defaultState;
return state;
default:
break;
}
return appReducer(state, action);
};
로그아웃 시 상태 리셋을 위한 호출 액션
function* logoutUser(action) {
try {
const response = yield call(UserLoginService.logout);
yield put(LoginActions.logoutSuccess());
} catch (error) {
toast.error(error.message, {
position: toast.POSITION.TOP_RIGHT
});
}
}
Dan Abramov의 답변으로는 파라미터화된 셀렉터의 캐시를 클리어할 수 없습니다.다음과 같은 셀렉터가 있는 경우:
export const selectCounter1 = (state: State) => state.counter1;
export const selectCounter2 = (state: State) => state.counter2;
export const selectTotal = createSelector(
selectCounter1,
selectCounter2,
(counter1, counter2) => counter1 + counter2
);
그런 다음 로그아웃 시 다음과 같이 릴리스해야 합니다.
selectTotal.release();
그렇지 않으면 실렉터의 마지막 콜에 대해 메모된 값과 마지막 파라미터 값은 메모리에 남습니다.
코드 샘플은 ngrx 문서에서 가져온 것입니다.
나에게 효과가 있는 빠르고 쉬운 옵션은 redux-reset을 사용하는 것이었습니다.이것은 간단하며 더 큰 앱을 위한 몇 가지 고급 옵션도 있습니다.
작성 스토어에서의 셋업
import reduxReset from 'redux-reset'
// ...
const enHanceCreateStore = compose(
applyMiddleware(...),
reduxReset() // Will use 'RESET' as default action.type to trigger reset
)(createStore)
const store = enHanceCreateStore(reducers)
로그아웃 기능으로 '리셋' 디스패치
store.dispatch({
type: 'RESET'
})
Redux Toolkit을 사용한 접근법:
export const createRootReducer = (history: History) => {
const rootReducerFn = combineReducers({
auth: authReducer,
users: usersReducer,
...allOtherReducers,
router: connectRouter(history),
});
return (state: Parameters<typeof rootReducerFn>[0], action: Parameters<typeof rootReducerFn>[1]) =>
rootReducerFn(action.type === appActions.reset.type ? undefined : state, action);
};
왜 그냥 사용하지 않는거죠?return module.exports.default()
export default (state = {pending: false, error: null}, action = {}) => {
switch (action.type) {
case "RESET_POST":
return module.exports.default();
case "SEND_POST_PENDING":
return {...state, pending: true, error: null};
// ....
}
return state;
}
주의: 액션 기본값을 다음과 같이 설정하십시오.{}
이 경우 체크박스를 때문에 .action.type
statementswitch 내부로 합니다.
또 다른 옵션은 다음과 같습니다.
store.dispatch({type: '@@redux/INIT'})
'@@redux/INIT'
는 redux가 redux를 사용할 때 입니다.createStore
모든 리듀서가 이미 디폴트값이 되어 있다고 가정하면 리듀서가 디폴트값이 디폴트값이 되어 상태가 새롭게 시작됩니다.단, redex의 프라이빗 구현 세부사항으로 간주될 수 있으므로 구매자는 주의하시기 바랍니다.
저에게 가장 효과가 있었던 것은,initialState
state
:
const reducer = createReducer(initialState,
on(proofActions.cleanAdditionalInsuredState, (state, action) => ({
...initialState
})),
단일 리듀서를 리셋하는 경우
예를들면
const initialState = {
isLogged: false
}
//this will be your action
export const resetReducer = () => {
return {
type: "RESET"
}
}
export default (state = initialState, {
type,
payload
}) => {
switch (type) {
//your actions will come her
case "RESET":
return {
...initialState
}
}
}
//and from your frontend
dispatch(resetReducer())
언급URL : https://stackoverflow.com/questions/35622588/how-to-reset-the-state-of-a-redux-store
'programing' 카테고리의 다른 글
열려 있는 MySQL 연결 수를 확인하려면 어떻게 해야 합니까? (0) | 2022.10.13 |
---|---|
GitHub에서 Python 패키지를 설치하는 방법은? (0) | 2022.10.13 |
jQuery.parseJSON이 JSON에서 이스케이프된 단일 따옴표로 인해 "Invalid JSON" 오류를 발생시킵니다. (0) | 2022.10.13 |
리스트 내의 고유값 발생을 카운트하려면 어떻게 해야 합니까? (0) | 2022.10.03 |
MySQLdb를 사용하여 커서를 닫아야 하는 경우 (0) | 2022.10.03 |