[React] ์ƒํƒœ๊ด€๋ฆฌ Redux / ContextAPI

์—๊ตฌ๋งˆยท2022๋…„ 4์›” 4์ผ
0

FrontEnd

๋ชฉ๋ก ๋ณด๊ธฐ
7/25

โš™๏ธRedux๊ฐ€ ์ข‹์€์ ?

๐Ÿ‘๐Ÿป props ์ „์†ก ๊ณผ์ • ์—†์ด ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ state์— ์ ‘๊ทผํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค!
๐Ÿ‘๐Ÿป ์ƒํƒœ๊ด€๋ฆฌ์— ์œ ์šฉ

์„ค์น˜

npm install react-router-dom
npm install redux react-redux

๊ธฐ๋ณธ ์„ธํŒ…

  • index.js
import { BrowserRouter } from 'react-router-dom';
import {Provider} from 'react-redux';
import {createStore} from 'redux';

const reduxState = 100;
function reducer(state = reduxState, action){
  return state
}
let store = createStore(reducer)

ReactDOM.render(
  <BrowserRouter>
    <Provider store={store}>
      <Redux />
    </Provider>
  </BrowserRouter>,
  document.getElementById('root')
);

๐Ÿ‘๐Ÿป Provider์—์„œ ๋„˜๊ฒจ์ค€ state๋Š” <Redux /> ๋ฟ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ๊บผ๋‚ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค!

๐Ÿ‘ Component์—์„œ state ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

useSelector, useDispatch ๋“ฑ ํŽธํ•œ ํ›…์Šค๊ฐ€ ์žˆ์–ด์„œ connectํ•จ์ˆ˜๋ฅผ ๋งŽ์ด์“ฐ์ง„ ์•Š๋Š”๋‹ค

useSelector

  • Redux.js
import React from 'react'; 
import {useSelector} from 'react-redux';

function Redux(){

    const gotReduxState = useSelector( (state) => state);

    return(
        <div>
             ๋ฐ›์•„์˜จ redux state : {gotReduxState} (useSelector)
        </div>
    )
}

export default Redux;

connect

  • Redux.js
import React from 'react'; 

function Redux(props){
    return (
        <div>
        	๋ฐ›์•„์˜จ redux state : {props.gotReduxState} (connect)
        </div>
    )
}

function stateToProps(props){ 
    return {
        gotReduxState : props
    }
}

export default connect(stateToProps)(Redux);

๊ฒฐ๊ณผ๋Š” ๊ฐ™๋‹ค! (์†Œ์Šค์ฝ”๋“œ)

๐Ÿ‘ ์ƒํƒœ๊ด€๋ฆฌ

reducer action

//index.js
const reduxState = 100;
function reducer(state = reduxState, action){
  if (action.type === "plus"){
    state++;
    return state 
  }
  else{
    return state
  }
}
let store = createStore(reducer);

reducer dispatch

//Redux.js
function Redux(){
    const gotReduxState = useSelector( (state) => state);
    const dispatch = useDispatch();
    return(
        <div>
            <button onClick={()=>{ dispatch( {type:'plus'} ) }}> PLUS </button>
        </div>
    )
}

export default Redux;

์—ฌ๋Ÿฌ๊ฐœ์˜ reducer

๐ŸŒŸ store๋Š” ํ•˜๋‚˜์—ฌ์•ผ ํ•œ๋‹ค !!
reducer๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ๋ผ๋ฉด ? combineReducers!

// index.js
const reduxState = 100;
function reducer(state = reduxState, action){
  if (action.type === "plus"){
    state++;
    return state 
  } else{
    return state
  }
}

const reduxState2 = 200;
function reducer2(state = reduxState2, action){
  if (action.type === "plus"){
    state++;
    return state 
  } else{
    return state
  }
}

let store = createStore(combineReducers({reducer, reducer2}));
//Redux.js
const gotReduxState = useSelector( (state) => state.reducer);

useSelector ์ธ์ž๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜
๊ทธ ์ฝœ๋ฐฑํ•จ์ˆ˜์˜ ์ธ์ž๋กœ state๊ฐ€ ์ „๋ถ€ ํฌํ•จ๋œ ๊ฐ์ฒด, ์ฆ‰ index.js์—์„œ Provider๋กœ ๋„˜๊ฒจ์ค€ store์˜ reducer์˜ state๊ฐ์ฒด(๊ฐ’)

const gotReduxState = useSelector( (state) => console.log(state));

์—ฌ๋Ÿฌ๊ฐœ์˜ reducer๋ฅผ combineํ•ด์„œ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  state๊ฐ์ฒด๋ฅผ ์ง€์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค!

    const gotReduxState = useSelector( (state) => state.reducer);

useReducer

๐Ÿค” useDispatch ๋Š” Store์˜ ๊ธฐ๋Šฅ์ธ dispatch๋ฅผ ํ•จ์ˆ˜์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” hook ์ž…๋‹ˆ๋‹ค.
๋งˆ์ฐฌ๊ฐ€์ง€๋กœ (reducer,์ดˆ๊ธฐ์ƒํƒœ)๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ํ›…์Šค๊ฐ€ useReducer
const [state, dispatch] = useReducer(reducer, initialState);
์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์— ๊ฑธ์ณ ์‚ฌ์šฉ๋˜๊ณ  ์ˆ˜์ •๋˜๋Š” state๋ผ๋ฉด useState ๋Œ€์‹  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

// Redux.js์—์„œ
import child from './Child'
< Child />
//Child.js
import React, {useReducer} from 'react'; 

const initialState = {
    inputs: {
      value: 'InitialStateValue',
    }
}
function reducer(state, action) {
    if (action.type === 'change'){
        return {
            ...state,
            inputs: {
              ...state.inputs,
              value: action.payload
            }
          };
    }
    return state;
  }
  
function UseReducer(){
    const [state, dispatch] = useReducer(reducer, initialState);
    return(
        <div>
            UseReducer.js์—์„œ {state.inputs.value}
            <button onClick={()=>{ dispatch( {type:'change', payload:'NewStateValue'} ) }}> CHANGE </button>
        </div>
    )
}

export default UseReducer;



โš™๏ธ Context API

  • ํ”„๋กœ์ ํŠธ์—์„œ ์ „์—ญ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ๊ด€๋ฆฌ
    ๊ฐ’ ๋˜๋Š” ์ƒํƒœ, ํ•จ์ˆ˜, ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ธ์Šคํ„ด์Šค , DOM ๋“ฑ๋„ ๊ฐ€๋Šฅ

< ContetAPI์™€ dispatch๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์ œ >

React.createContext()

export const UserDispatch = React.createContext(null);

createContext์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” Context์˜ ๊ธฐ๋ณธ๊ฐ’์ด๋‹ค.

.Provider

  const [state, dispatch] = useReducer(reducer, initialState);
	...
   return(
    <UserDispatch.Provider value={dispatch}>
      <CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      <UserList users={users} onToggle={onToggle} onRemove={onRemove} />
    </UserDispatch.Provider>

<UserList >์•ˆ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด <User >๊ฐ€ ์žˆ๋‹ค๋ฉด,

  return (
   <div>
     {users.map(user => (
       <User user={user} key={user.id} />
     ))}
   </div>
 );

<User > ์—์„œ๋„ dispatch์— ์ ‘๊ทผํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  const dispatch = useContext(UserDispatch);
 return (
   <div>
     <b
       onClick={() => {
         dispatch({ type: 'TOGGLE_USER', id: user.id });
       }}
     >
    ...

์ „๋‹ฌํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ
export const ์ด๋ฆ„ = React.createContext();
<์ด๋ฆ„.Provider value = {์ „๋‹ฌํ• ๊ฐ’}>
<์ „๋‹ฌ๋ฐ›์„ ์ปดํฌ๋„ŒํŠธ />
</์ด๋ฆ„.Provider>

์ „๋‹ฌ๋ฐ›์„ ์ปดํฌ๋„ŒํŠธ์—์„œ
const ๋ฐ›์•„์„œ์ €์žฅํ• ์ด๋ฆ„ = useContext(์ „๋‹ฌ ์ด๋ฆ„);

profile
์ฝ”๋”ฉํ•˜๋Š” ๊ณ ๊ตฌ๋งˆ ๐Ÿ  Life begins at the end of your comfort zone

0๊ฐœ์˜ ๋Œ“๊ธ€