Redux 스토어의 상태를 재설정하는 방법은 무엇입니까?


455

상태 관리를 위해 Redux를 사용하고 있습니다.
상점을 초기 상태로 재설정하는 방법

예를 들어 두 개의 사용자 계정 ( u1u2) 이 있다고 가정 해 보겠습니다 .
다음과 같은 일련의 이벤트를 상상해보십시오.

  1. 사용자 u1가 앱에 로그인하여 무언가를 수행하므로 저장소에 일부 데이터를 캐시합니다.

  2. 사용자가 u1로그 아웃했습니다.

  3. 사용자 u2는 브라우저를 새로 고치지 않고 앱에 로그인합니다.

이 시점에서 캐시 된 데이터가에 연결 u1되고 정리하고 싶습니다.

첫 번째 사용자가 로그 아웃 할 때 Redux 스토어를 초기 상태로 재설정하려면 어떻게해야합니까?


8
대신 보안 관점에서 로그 아웃시 상태를 지우는 것이 좋습니다.
Clarkie

답변:


1033

그렇게하는 한 가지 방법은 응용 프로그램에서 루트 감속기를 작성하는 것입니다.

루트 리듀서는 일반적으로 작업 처리를로 생성 된 리듀서에 위임합니다 combineReducers(). 그러나 USER_LOGOUT액션 을받을 때마다 초기 상태를 다시 한 번 반환합니다.

예를 들어 루트 리듀서가 다음과 같은 경우

const rootReducer = combineReducers({
  /* your app’s top-level reducers */
})

이름을 바꾸고 appReducerrootReducer위임을 작성할 수 있습니다 .

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') {
    state = undefined
  }

  return appReducer(state, action)
}

이제, USER_LOGOUT발사 할 때마다 모든 감속기가 새로 초기화됩니다. 그들은 또한 그들이 확인 할 수 있기 때문에 그들이 원한다면 처음과 다른 것을 반환 할 수 action.type있습니다.

반복해서 말하면 완전히 새로운 코드는 다음과 같습니다.

const appReducer = combineReducers({
  /* your app’s top-level reducers */
})

const rootReducer = (state, action) => {
  if (action.type === 'USER_LOGOUT') {
    state = undefined
  }

  return appReducer(state, action)
}

여기서 상태를 변경하지 않고 다른 함수에 전달하기 전에 호출 된 로컬 변수 의 참조다시 할당하는 것 입니다 state. 상태 객체를 변경하면 Redux 원칙을 위반하게됩니다.

redux-persist를 사용하는 경우 스토리지를 청소해야 할 수도 있습니다. Redux-persist는 상태 엔진을 스토리지 엔진에 보관하며 새로 고칠 때 상태 사본이로드됩니다.

먼저 적절한 스토리지 엔진 을 가져 와서 설정하기 전에 상태를 구문 분석 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')

        state = undefined;
    }
    return appReducer(state, action);
};

15
댄이 궁금합니다. 감속기에서 이와 같은 일을 할 수 있습니까? CLEAR_DATA가 조치입니다. case 'CLEAR_DATA': return initialState
HussienK

6
@HussienK는 작동하지만 모든 감속기의 상태에서는 작동하지 않습니다.
Cory Danielson

12
다음은 비동기 감속기를 사용하는 경우 감속기를 동적으로 결합하는 버전입니다.export const createRootReducer = asyncReducers => { const appReducer = combineReducers({ myReducer ...asyncReducers }); return (state, action) => { if (action.type === 'LOGOUT_USER') { state = undefined; } return appReducer(state, action); } };
Ivo Sabev

2
if (action.type === 'RESET') return action.stateFromLocalStorage
Dan Abramov

3
이 접근법은 국가와 모든 역사를 완전히 정리하고 있습니까? 보안 관점에서 생각하고 있습니다.이 USER_LOGOUT작업이 실행되면 일단 작업이 시작 되면 이전부터 상태 데이터를 얻을 수 있습니까? (예 : devtools를 통해)
AlexKempton

81

Dan Abramov가 승인 한 의견은이 접근 방식과 함께 반응 라우터 리덕스 패키지를 사용할 때 이상한 문제가 발생하는 것을 제외하고는 정확하다고 지적하고 싶습니다. 우리의 수정은 상태를 설정하지 undefined않고 현재 라우팅 감속기를 사용하는 것이 었습니다 . 이 패키지를 사용하는 경우 아래 솔루션을 구현하는 것이 좋습니다.

const rootReducer = (state, action) => {
  if (action.type === 'USER_LOGOUT') {
    const { routing } = state
    state = { routing } 
  }
  return appReducer(state, action)
}

19
여기서 로그 아웃하면 로그 아웃시 전체 상태 트리를 지우고 싶지 않을 수 있습니다. 접근 방식은 모든 하위 트리의 루트 리듀서에서 동일하게 작동 하므로이 기술을 루트 리듀서에서만 적용하는 것이 더 명확 할 수 있습니다 서브 트리 (들) 당신이 '특별한'어린이 골라보다는 지우려 하지 같이, 전체 트리의 루트 감속기에서 명확를
davnicwil

1
나는 당신이 지금 언급하고있는이 문제를 겪고 있다고 생각합니다 (로그 아웃에서 경로를 올바른 경로로 설정하지만 완전히 다른 구성 요소가로드 될 것입니다). 나는 그것을 고치기 위해 당신과 비슷한 것을 구현했지만, 불변의 js가 이것을 정리하고 있습니다. 나는 RESET-STATE 액션을 가진 부모 감속기를
만들었고,

비슷한 문제가 발생하여 문제가 해결되었습니다. 감사.
로이드 왓킨

3
react-redux-router를 사용하면이 속성은 routerNOTrounting
Mr.

2
@Mrchief 그것은 당신이 당신의 그것에서 정의한 것에 달려있다 combineReducers()..... 만약 당신이 combineReducers({routing: routingReducer})대답에 설명 된 것처럼 될 것입니다
Ben Lonsdale

40

조치를 정의하십시오.

const RESET_ACTION = {
  type: "RESET"
}

그런 다음 각 감속기를 통해 여러 작업을 사용 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조치 를 호출 할 때마다 리듀서가 상점을 기본 상태로 업데이트합니다.

이제 로그 아웃을 위해 다음과 같이 처리 할 수 ​​있습니다.

const logoutHandler = () => {
    store.dispatch(RESET_ACTION)
    // Also the custom logic like for the rest of the logout handler
}

브라우저를 새로 고치지 않고 사용자가 로그인 할 때마다 상점은 항상 기본값입니다.

store.dispatch(RESET_ACTION)아이디어를 정교화합니다. 목적에 맞는 액션 제작자가있을 것입니다. 더 좋은 방법은 당신이 있습니다 LOGOUT_ACTION.

당신이 이것을 파견하면 LOGOUT_ACTION. 그런 다음 사용자 정의 미들웨어가 Redux-Saga 또는 Redux-Thunk를 사용하여이 조치를 가로 챌 수 있습니다. 그러나 두 가지 방법 모두 다른 조치 '재설정'을 발송할 수 있습니다. 이 방법으로 상점 로그 아웃 및 재설정은 동 기적으로 발생하며 상점은 다른 사용자 로그인을 준비합니다.


1
나는 이것이 undefined다른 대답 에서처럼 상태를 설정하는 것보다 더 나은 접근법 이라고 생각합니다. 응용 프로그램이 상태 트리를 기대하고 undefined대신 트리를 제공 하면 빈 트리보다 처리해야 할 버그와 두통이 더 많습니다.
worc

3
@worc 감속기는 정의되지 않은 상태를 수신하면 initialState를 반환하므로 상태는 실제로 정의되지 않습니다.
Guillaume

3
@worc은이 접근법을 사용하면 누구나 새로운 리듀서를 만들 때마다 리셋 케이스를 추가해야한다는 것을 기억해야합니다.
Francute

1
나는 두 가지 이유와 RESET_ACTION이 액션 이라는 아이디어에 대해 분명히 마음을 바꿨습니다 . 따라서 감속기에는 실제로 속하지 않습니다.
worc

1
이것이 바로 올바른 접근법입니다. 초기 상태 이외의 상태로 설정하는 것은 문제를 요구합니다
Sebastian Serrano

15

최상의 답변에 대한 간단한 답변 :

const rootReducer = combineReducers({
    auth: authReducer,
    ...formReducers,
    routing
});


export default (state, action) =>
  rootReducer(action.type === 'USER_LOGOUT' ? undefined : state, action);

이것은 감사합니다. Dan의 대답에서 왔지만 이해할 수 없습니다.
Aljohn Yamaro

14
 const reducer = (state = initialState, { type, payload }) => {

   switch (type) {
      case RESET_STORE: {
        state = initialState
      }
        break
   }

   return state
 }

초기 저장소로 재설정하려는 모든 또는 일부 감속기에서 처리하는 작업을 실행할 수도 있습니다. 한 번의 작업으로 전체 상태로 재설정하거나 자신에게 적합한 부분 만 재설정 할 수 있습니다. 나는 이것이 가장 간단하고 제어 가능한 방법이라고 생각합니다.


10

Redux를 사용하면 다음 솔루션을 적용 한 경우 모든 감속기에서 initialState를 설정했다고 가정합니다 (예 : {user : {name, email}}). 많은 구성 요소에서 이러한 중첩 속성을 확인 하므로이 수정 사항을 사용하면 결합 된 속성 조건에서 렌더링 메서드가 손상되는 것을 방지합니다 (예 : state.user.email, 위에서 언급 한 솔루션 인 경우 오류가 발생하는 경우 사용자가 정의되지 않음).

const appReducer = combineReducers({
  tabs,
  user
})

const initialState = appReducer({}, {})

const rootReducer = (state, action) => {
  if (action.type === 'LOG_OUT') {
    state = initialState
  }

  return appReducer(state, action)
}

7

NGRX4 업데이트

NGRX 4로 마이그레이션하는 경우 마이그레이션 가이드 에서 감속기를 결합하기위한 rootreducer 방법이 ActionReducerMap 방법으로 대체되었음을 알 수 있습니다. 처음에,이 새로운 일을하는 방식은 상태를 재설정하는 것을 어렵게 만들 수 있습니다. 실제로는 간단하지만이를 수행하는 방법이 변경되었습니다.

이 솔루션은 NGRX4 Github 문서 의 메타 리듀서 API 섹션에서 영감을 얻었습니다 .

먼저 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와 동일한 영향을 미치는 한 가지 방법입니다.


5

router상태 를 유지 하고 상태 트리의 다른 모든 것을 초기화 하기 위해 Dan, Ryan 및 Rob의 접근 방식을 결합하여 결과 는 다음과 같습니다.

const rootReducer = (state, action) => appReducer(action.type === LOGOUT ? {
    ...appReducer({}, {}),
    router: state && state.router || {}
  } : state, action);

4

Redux에 상태 재설정 기능을 제공하는 구성 요소를 만들었습니다.이 구성 요소를 사용하여 상점을 향상시키고 특정 action.type을 전달하여 재설정을 트리거하면됩니다. 구현에 대한 생각은 @Dan Abramov가 말한 것과 동일합니다.

Github : https://github.com/wwayne/redux-reset


4

상태를 지우는 작업을 만들었습니다. 따라서 로그 아웃 작업 작성자를 발송하면 상태를 지우는 작업도 발송됩니다.

사용자 기록 작업

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
  }
};

이것이 최적인지 확실하지 않습니까?


2

당신이 사용하는 경우 REDUX-작업을 여기에 HOF (사용 빠른 해결의 높은 주문 기능 )에 대한이 handleActions.

import { handleActions } from 'redux-actions';

export function handleActionsEx(reducer, initialState) {
  const enhancedReducer = {
    ...reducer,
    RESET: () => initialState
  };
  return handleActions(enhancedReducer, initialState);
}

그런 다음 감속기 처리를 위해 handleActionsEx원본 대신 사용하십시오 handleActions.

Dan의 대답 은이 문제에 대한 훌륭한 아이디어를 제공하지만을 사용하고 있기 때문에 잘 작동하지 않았습니다 redux-persist.
와 함께 사용하면 redux-persist단순히 전달 undefined상태가 지속 동작을 트리거하지 않으므로 저장소에서 항목을 수동으로 제거해야한다는 것을 알았습니다 (따라서 React Native AsyncStorage).

await AsyncStorage.removeItem('persist:root');

또는

await persistor.flush(); // or await persistor.purge();

나를 위해 일하지 않았다-그들은 단지 나에게 소리 쳤다. (예 : "예기치 않은 키 _persist ..." 와 같은 불평 )

그런 다음 갑자기 RESET액션 유형이 발생 했을 때 모든 개별 감속기가 자신의 초기 상태를 반환하게 만드는 것만으로 고민했습니다 . 이렇게하면 지속이 자연스럽게 처리됩니다. 분명히 위의 유틸리티 함수 ( handleActionsEx)가 없으면 내 코드는 DRY처럼 보이지 않지만 (단 하나의 라이너 일지라도 RESET: () => initialState) 메타 프로그래밍을 좋아합니다.


2

다음 해결책이 나를 위해 일했습니다.

메타 감속기에 재설정 상태 기능을 추가했습니다.

return reducer(undefined, action);

모든 감속기를 초기 상태로 설정합니다. undefined대신 상점 구조가 손상되어 반품 으로 인해 오류가 발생했습니다.

/reducers/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.module.ts

import { StoreModule } from '@ngrx/store';
import { metaReducers, reducers } from './reducers';

@NgModule({
  imports: [
    StoreModule.forRoot(reducers, { metaReducers })
  ]
})
export class AppModule {}

2

보안 관점에서 가장 안전한 것은 사용자 아웃 로그인하는 모든 영속 상태를 재설정 할 때 어떻게 (예 : 쿠키,하는 localStorage, IndexedDB, Web SQL, 등) 및 사용하여 페이지의 새로 고침을 window.location.reload(). 부주의 한 개발자가 실수로 또는 의도적으로 일부 민감한 데이터를 windowDOM 등에 저장 했을 수 있습니다. 모든 영구 상태를 날려 버리고 브라우저를 새로 고치는 것이 이전 사용자의 정보가 다음 사용자에게 유출되지 않도록하는 유일한 방법입니다.

(물론, 공유 컴퓨터 사용자는 "개인 정보 보호 브라우징"모드를 사용하고, 브라우저 창을 직접 닫고, "브라우징 데이터 지우기"기능을 사용해야합니다. 그러나 개발자는 모든 사람이 항상 부지런한)


1
사람들이 왜 이것을 다운 보트 했습니까? 빈 내용으로 새로운 redux 상태를 수행하면 기본적으로 여전히 메모리에 이전 상태가 있으며 이론적으로 데이터에서 액세스 할 수 있습니다. 브라우저를 새로 고침하는 것이 가장 안전한 방법입니다!
Wilhelm Sorban

2

Dan의 답변 위에 빌드 된 타이프 스크립트로 작업 할 때의 해결 방법 (redux 타이핑을 사용하면 undefined감속기로 첫 번째 인수로 전달할 수 없으므로 초기 루트 상태를 상수로 캐시합니다) :

// 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"})
  }
}

2

수락 된 답변은 제 사건을 해결하는 데 도움이되었습니다. 그러나 나는 전체가 아닌 상태를 해결 해야하는 경우를 만났습니다. 그래서-나는 이것을 이렇게했다 :

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;

희망이 이것이 다른 누군가를 돕기를 바랍니다 :)


상태가 10 개를 초과하지만 하나의 감속기의 상태를 재설정하려면 어떻게해야합니까?
바울

1

@ dan-abramov 답변 의 확장으로 때로는 특정 키가 재설정되지 않도록 유지해야 할 수도 있습니다.

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);
};

1

나를 위해 빠르고 쉬운 옵션은 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'
})

도움이 되었기를 바랍니다


1

Redux가 초기 상태의 동일한 변수를 참조하지 않도록하기 위해 노력합니다.

// 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;
  }
};

함수로 기본 상태를 작성한다는 아이디어는 실제로 하루를 절약했습니다. 감사합니다 🙏
Chris Paul

0

이 접근 방식은 매우 정확합니다. 특정 상태 "NAME"을 (를) 파괴하여 다른 사람을 무시하고 유지하십시오.

const rootReducer = (state, action) => {
    if (action.type === 'USER_LOGOUT') {
        state.NAME = undefined
    }
    return appReducer(state, action)
}

하나의 상태 트리 만 재설정해야하는 경우 USER_LOGOUT해당 리듀서에서 수신 대기 하고 처리 할 수도 있습니다.
Andy_D

0

왜 당신은 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 기본값을로 설정 하고 switch 문 내부 {}를 확인할 때 오류가 발생하지 않기 때문에 괜찮습니다 action.type.


0

내가 허용 대답은 나를 위해 잘 작동 발견,하지만이 ESLint의 트리거 no-param-reassign오류 - https://eslint.org/docs/rules/no-param-reassign

다음은 상태를 복사하여 처리하는 방법입니다 (상태를 이해하기 위해 Reduxy에서 수행 할 작업입니다 ...).

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)
}

0

Dan Abramov의 답변 외에도 state = undefined와 함께 action = {type : '@@ INIT'}로 action을 명시 적으로 설정해서는 안됩니다. 위의 조치 유형을 사용하면 모든 감속기가 초기 상태를 리턴합니다.


0

서버에서 변수는 global.isSsr = true 이고 각 감속기에는 const가 있습니다. initialState 저장소의 데이터를 재설정하려면 각 감속기로 다음을 수행하십시오. appReducer.js 사용 예 :

 const initialState = {
    auth: {},
    theme: {},
    sidebar: {},
    lsFanpage: {},
    lsChatApp: {},
    appSelected: {},
};

export default function (state = initialState, action) {
    if (typeof isSsr!=="undefined" && isSsr) { //<== using global.isSsr = true
        state = {...initialState};//<= important "will reset the data every time there is a request from the client to the server"
    }
    switch (action.type) {
        //...other code case here
        default: {
            return state;
        }
    }
}

마지막으로 서버의 라우터에서 :

router.get('*', (req, res) => {
        store.dispatch({type:'reset-all-blabla'});//<= unlike any action.type // i use Math.random()
        // code ....render ssr here
});

0

다음 해결책이 저에게 효과적입니다.

처음에 시작 우리의 응용 프로그램의 감속기 상태는 신선 하고 새로운 기본적으로 초기 상태 (Initial) .

기본 상태 를 유지하려면 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
    });
  }
}

이것이 문제를 해결하기를 바랍니다.


0

상태를 초기 상태로 재설정하기 위해 다음 코드를 작성했습니다.

const appReducers = (state, action) =>
   combineReducers({ reducer1, reducer2, user })(
     action.type === "LOGOUT" ? undefined : state,
     action
);

0

허용 된 답변의 해결책으로 할 수없는 한 가지는 매개 변수가있는 선택기의 캐시를 지우는 것입니다. 이와 같은 선택 기가있는 경우 :

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 문서 에서 가져온 것 입니다.


0

나를 위해 가장 효과가 있었던 것은 initialState대신 다음 을 설정하는 것입니다 state.

  const reducer = createReducer(initialState,
  on(proofActions.cleanAdditionalInsuredState, (state, action) => ({
    ...initialState
  })),

-1

다른 옵션은 다음과 같습니다.

store.dispatch({type: '@@redux/INIT'})

'@@redux/INIT'은 당신이했을 때 redux가 자동으로 디스패치하는 액션 타입입니다 createStore. 따라서 리듀서가 모두 기본값을 가지고 있다고 가정하면, 이것에 의해 잡히고 상태가 새로 시작됩니다. redux의 개인 구현 세부 사항으로 간주 될 수 있으므로 구매자는 조심해야합니다 ...


나는 그것이 상태를 바꾸지 않고 있다고 말했다. 또한 ReduxDevtools에 첫 번째 조치로 표시되는 @@ INIT를 시도했다
Reza

-3

로그 아웃 링크에서 세션을 지우고 페이지를 새로 고치면됩니다. 상점에 추가 코드가 필요하지 않습니다. 상태를 완전히 재설정하려는 경우 언제든지 페이지 새로 고침을 간단하고 쉽게 반복하여 처리 할 수 ​​있습니다.


1
상점을 로컬 스토리지에 동기화하는 미들웨어를 사용하는 경우 어떻게됩니까? 그러면 당신의 접근 방식이 전혀 작동하지 않습니다 ...
Spock

8
사람들이 왜 이런 식으로 답을 내리는 지 이해가 가지 않습니다.
Wylliam Judd

사람들이 왜 이것을 다운 보트 했습니까? 빈 내용으로 새로운 redux 상태를 수행하면 기본적으로 여전히 메모리에 이전 상태가 있으며 이론적으로 데이터에서 액세스 할 수 있습니다. 브라우저를 새로 고침하는 것이 가장 안전한 방법입니다!
Wilhelm Sorban

-3

onLogout() {
  this.props.history.push('/login'); // send user to login page
  window.location.reload(); // refresh the page
}


설명? @SinanSamet
Nikita Beznosikov

분명히 나는 ​​이것을 투표하지 않았다. 그러나 나는 그것을 낙담시킵니다. 로그인 및 다시로드로 이동하면 아마도 로그 아웃 할 것입니다. 그러나 당신이 당신의 상태를 잃었 기 때문에. redux-persist를 사용하지 않으면 로그 아웃조차되지 않습니다. 전반적으로, 나는 다음과 같은 기능을 보는 것을 싫어합니다.window.location.reload();
Sinan Samet

-이와 같은 기능을 작성하지 마십시오. - 왜? -싫어요.
니키타 베즈 노시 코프

1
페이지를 다시로드하면 상점 상태를 재설정하는 것과 다릅니다. 또한 window반응이 없는 환경 일 수도 있습니다.
Max
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.