Skip to content

Instantly share code, notes, and snippets.

@qkreltms
Last active February 12, 2021 12:16
Show Gist options
  • Select an option

  • Save qkreltms/eecd70c1c58919bdc17c63b8c8f0c622 to your computer and use it in GitHub Desktop.

Select an option

Save qkreltms/eecd70c1c58919bdc17c63b8c8f0c622 to your computer and use it in GitHub Desktop.
const initialState: State = {
  user: {
    id: '',
    nickname: '',
    photoURL: '',
    statusMessage: '',
  },
  deleteMode: false,
  // ref를 주입받을 modal state입니다.
  modal: undefined,
};

// showModal action입니다.
const showModal = (dispatch: React.Dispatch<Action>) => ({
  user,
  deleteMode,
  onDeleteFriend,
  onAddFriend,
}: ShowModalParams): void => {
  dispatch({
    type: ActionType.ShowModal,
    payload: {
      user,
      deleteMode,
      onDeleteFriend,
      onAddFriend,
    },
  });
};

// 액션을 처리할 Reducer입니다.
const reducer: Reducer = (state = initialState, action) => {
  const { type, payload } = action;
  const { modal } = state;
  switch (type) {
    case ActionType.ShowModal:
      if (modal && modal.current) {
        modal.current.setUser(payload.user);
        modal.current.showAddBtn(!payload.deleteMode);
        modal.current.open();
      }
      return {
        ...state,
        user: payload.user,
        deleteMode: !payload.deleteMode,
      };
    default:
      return state;
  }
};

// provider로 하위 컴포넌트에 showModal 액션을 전달해 줍니다.
function ProfileModalProvider(props: Props): React.ReactElement {
  const [state, dispatch] = useReducer<Reducer>(reducer, initialState);

  const actions = {
    showModal: showModal(dispatch),
  };

  return <Provider value={{ state, ...actions }}>{props.children}</Provider>;
}
// 모바일 앱이지만, 웹과 비슷합니다.
//우리의 modal 컴포넌트가 있는 곳입니다. 웹에 비유하면 App.jsx 위치쯤이라 보면 됩니다.

function RootNavigator(): ReactElement {
  const navigation = useNavigation();
  const { state } = useProfileContext();
  const modalEl = useRef(null);
  // 컨텍스트에 modal ref를 주입해줍니다.
  state.modal = modalEl;
  return (
    <View
      style={{
        flex: 1,
        flexDirection: 'column',
      }}
    >
      // ...
      // 우리의 Modal 컴포넌트!
      <ProfileModal
        testID="modal"
        ref={state.modal}
        onChatPressed={(): void => {
          if (state.modal && state.modal.current) {
            state.modal.current.close();
          }
          navigation.navigate('Message');
        }}
      />
    </View>
  );
}
// 이제 원하는 컴포넌트에 Provider로 액션을 전달하고 원하는 때에 액션을 dispatch 하면 됩니다. 
    <ProfileModalProvider>
      <RootComponent />
    </ProfileModalProvider>
    ```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment