ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [리엑트]리덕스,리듀서 이해하기
    프론트엔드/리엑트 2023. 7. 11. 18:03
    728x90
    상태관리 라이브러리이다.
    store에 state(변수)를 저장하고 관리한다.

     

    index.tsx

     

    import { Provider } from 'react-redux'
    import { createStore } from 'redux'
    import rootReducer from './reducers'
    const store = createStore(rootReducer, composeWithDevTools())
    root.render(
    <React.StrictMode>
    <Provider store={store}>
    <App />
    </Provider>
    </React.StrictMode>
    )

     

    사용하기 위한 import와 설정을 해준다.

    provider의 역할은 우리의  App이 Redux.store에 접근을 할 수 있게 도와준다.

     


    reducers/index.tsx

     

    import { combineReducers } from 'redux'
    import headerReducer from './header/headerReducer'
    import modalReducer from './modal/modalReducer'
    import userReducer from './user/userReducer'
    import { persistReducer } from 'redux-persist'
    import storage from 'redux-persist/lib/storage'

    const rootReducer = combineReducers({
    headerReducer,
    userReducer,
    modalReducer
    })

    const persistConfig = {
    key: 'root',
    // localStorage에 저장합니다.
    storage,
    // auth, board, studio 3개의 reducer 중에 auth reducer만 localstorage에 저장합니다.
    whitelist: ['userReducer']
    // blacklist -> 그것만 제외합니다
    }

    export default persistReducer(persistConfig, rootReducer)
    export type RootState = ReturnType<typeof rootReducer>

     

    combineReducers 하나의 스토어에서 여러가지 리듀서를 사용가능하게 해준다

     

    persistConfig  whitelist : ['영속화 할 데이터'] : 영속화할 데이터를 설정하여, 관리해줄수있다.

     

    여기서, 영속화란?

    // 영속화 : 애플리케이션 데이터를 일정시간동안 유지, 애플리케이션을 종료해도 데이터를 보존하는것을 의미한다.
     
    // 1. 종료후에도 자동로그인 가능.
    2.새로고침이후에도 설정한 애플리케이션 환경을 유지.
    3. 사용자입력을 저장, 일시작업중단후에도 이어서가능.

    header.tsx

     

    import { useSelector, useDispatch } from 'react-redux'
    import { setSearchResults } from '../reducers/header/headerReducer'
    //사용자입력값
    const [inputcontent, setInputContent] = useState('')
    const getValue = (e: React.ChangeEvent<HTMLInputElement>) => {
    setInputContent(e.target.value);
    }

    const goSearch = (searchData: string) => {
    console.log(dispatch(setSearchResults(searchData)))
    goResultpage()
    }

     

    useState를 통해 초기 state값을 설정해주고,

    getValue를 선언한다.

    getValue는

    e:React.ChangeEvent<HTMLInputElement>  = input태그에서 발생한 change이벤트 태그를 가르킨다.

     

    setInputContent(e.target.value);

     

    change이벤트가 발생한 태그의 value값.

    즉, 입력창에 입력된값을 setInputContent()을 통해 inputcontent값을 업데이트 시켜준다.

     

     

    <div className="search_wrap">
    <input
    className="search_input"
    type="text"
    placeholder="검색어를 입력하세요"
    onChange={getValue}
    ></input>
    <button
    className="search_button"
    onClick={() => {
    goSearch(inputcontent)
    }}
    >
    검색
    </button>
    </div>

     

    버튼을 클릭했을 때 onClick이벤트가 실행되고, onClick함수가 실행되면 goSearch 함수가 실행되고 

    goSearch함수는 인자로 searchData를 갖는다.

    dispatch(setSearchResults(searchData))  디스패치를 통해 검색 할 입력값을 리듀서에 전달해준다.

     

    goSearch(Inputcontent) => 입력값을 goSearch함수에 담았고 goSearch(searchData:string) 으로 설정했다.

    즉 searchData = inputcontent 이므로 searchData에는 입력값이 담겨져서 넘어가게된다.

     


    headerReducer.tsx

    //액션타입생성
    const SET_SEARCH_RESULTS = 'header/SET_SEARCH_RESULTS'

    //액션 생성 함수
    export const setSearchResults = (searchData: string) => ({
    type: SET_SEARCH_RESULTS,
    payload: searchData
    })

    type HeaderAction = ReturnType<typeof setSearchResults>

     

    액션타입을 생성해준다.

    예를들어 SET_LOGIN , SET_JOIN 등 

    리듀서에서 처리해줄 때 if/else문 또는 swich/case로 해당타입일 때 실행되게 해줄것이다.

     

    액션생성 함수를 생성해준다.

    액션생성함수 setSearchResults에 디스패치로 가져 온 인자값 searchData를(사용자입력값) 인자로 받고

    type: 위에서 정해둔 액션타입

    payload: searchData 로 설정해준다.


    interface storeDTO {
    address: string
    avg_rating: number
    name: string
    rest_id: string
    url: string
    }

    현재 진행중인 프로젝트에서 검색기능(백쪽의 API)을 실행시켰을 때

    전달되는값들은 address,avg_rating,등 총 5가지를 받을 수 있고,

    그 값들을 코드의 가독성을 위해 storeDTO로  만들어주었다.


    //상태(state) 타입정의
    type PageState = {
    page: string
    searchResults: storeDTO[]
    }

    const initialState: PageState = {
    page: 'home',
    searchResults: []
    }

     

    리듀서에서 사용 할 state(상태)에 대한 정의 부분이다.

    상태정의와 초기값을 설정해준다.

     


    export default async function headerReducer(
    state: PageState = initialState,
    action: HeaderAction
    ) {
    switch (action.type) {
    case SET_SEARCH_RESULTS:
    const url = BaseUrl + '/restaurant/search/'
    axios
    .get(url, {
    params: {
    search: action.payload
    },
    headers: {
    'Content-Type': 'application/json'
    }
    })
    .then(function (response) {
    return (state.searchResults = response.data)
    })
    .catch(function (error) {
    alert('검색 오류')
    })
    break
    default:
    return state
    }
    }

    headerReducer이다.

     

    먼저, state와 action을 위에서 설정한대로 설정해준다.

     

    그리고 switch - case 구문을 통해

    action.type 즉 HeaderAction -> setSearchResults의 타입이

    SET_SEARCH_RESULTS 일때 실행된다.

     

    url은 swagger를 통해 back에서 생성,제공해 주는 url을 추가하고

    axios통신 get방식으로 search라는 이름으로 action.payload 즉 입력값을 전달해준다.

     

    서버에서 정상적으로 응답을 받게되면 then 구문이 실행되어

    searchResults가 업데이트된다.

     

    요청에서 오류가 발생하게된다면 .catch구문이 실행되어 검색오류 경고창이 발생한다.

     

    break는 현재 케이스의 구문이 완료가되면 다른케이스로 이동하지않게하기위해 사용했다

    break가 없다면 케이스구문이 완료가되도 다른케이스를 실행시켜 오류가 발생할수도있어, 오류방지를위해 사용한다.

     

    default: return state 를 설정해줘, 어떠한 타입의 케이스도 존재하지않을 때

    기본값으로 현재 state값을 그대로 return해준다.

     

    728x90

    댓글

Designed by Tistory.