Fullstack-Study-241204-250625

커리큘럼(12-30/변경)

01. Java
02. git
03. Database 
04. Jsp [Server]

05. HTML,CSS 
07. JS
06. 미니프로젝트-2W

08. SpringFramework , SrpingBoot 
19. 중간프로젝트 (1M)
10. Linux 명령어
11. AWS
12. Docker
13. Kubernetes
14. React JS (v)
15. App - Android
16. 최종프로젝트 (1M)(v)

React(리액트)

Redux

핵심개념

개념 설명
Store 애플리케이션의 상태를 전역으로 저장하는 객체
Action 상태에 어떤 변화가 필요한지 설명하는 객체 (type필수)
Reducer 이전 상태와 액션을 받아서 새로운 상태를 반환하는 함수
Dispatch Action을 리듀서에 보내 상태를 변경하는 함수
Subscribe 상태 변경을 감지하여 UI를 다시 렌더링하게끔 등록하는 함수

동작흐름

redux 동작흐름

  1. 컴포넌트(view)에서 dispatch(action) 실행
  2. Reducer가 현재 상태와 action을 기반으로 새로운 상태 생성
  3. 새 상태가 store에 저장됨
  4. subscribe된 컴포넌트들이 변경된 상태로 자동 업데이트 (useSelector() 가 처리함)
  1. 설치
//리덕스 설치
npm install redux react-redux
//리덕스 툴킷 설치 - 기존 리덕스 방식 deprecated됨에 따라 사용하는 새로운방식
npm install @reduxjs/toolkit

1. slice작성

 // CountReducer.js

const countSlice = createSlice({
    name : 'count', // 이름
    initialState : {value:0}, // state초기값
    reducers: { // 첫번째 매개변수에 state를 받고, 두번째 매개변수는 action을 받을 수 있음
        increase : (state) => {
            state.value +=1; // 리덕스 툴킷에서는 state를 바로 변경 가능
        },
        decrease : (state) => {
            state.value -=1;
        }

    }
});

// UserReducer.js
const userSlice = createSlice({
    name: 'user',
    initialState:{name:''},
    reducers:{ // action이라는 두번째 매개변수에 외부에서 전달받는값이 들어옴
        setName: (state,action)=>{
            console.log(action); // 외부에서 전달되는 값이 action의 payload속성에 전달됨
            state.name=action.payload;
        }
    }
})

export const {setName} = userSlice.actions;
export default userSlice.reducer;

export const {increase,decrease} = countSlice.actions; // 리듀서 반환
export default countSlice.reducer;
  • name : 실제로 사용자가 사용하지는 않지만 시스템 내부에서 동작할 때 사용
  • initalState : state의 초기값을 설정하는 곳으로 state에 여러 값 추가 가능
  • reducers : state의 값을 변경하는 함수를 생성하는 곳으로 각각의 함수에서 받는 매개변수중 첫번째는 state, **두번째는 외부에서 전달받는 값(action)**을 받을 수 있음.
  • 외부에서 받은 값action.payload로 받을 수 있음

2. store생성

// AppStore.js

// store - 애플리케이션의 상태를 전역적으로 저장하는 객체
// 리액트 툴킷의 configureStore가 제공
export const store = configureStore({
    reducer : {
        count : CountReducer,  // count key는 컴포넌트에서 사용되는 중요한 key가 됨
        user : UserReducer
    }
})
  • 작성한 reducer를 받아서 store에 저장
  • reducer안에 선언한 key값컴포넌트에서 state에서 호출하여 사용
  • key값에 매칭되는 값으로는 리듀서를 사용

3. 리액트 앱과 Redux를 연결(Provider컴포넌트)

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  /* 리덕스를 사용할 하위 객체에 Provider로 감싸줌(구독)*/
  <BrowserRouter>
    <Provider store={store}>  
      <App />
    </Provider>
  </BrowserRouter>
);
  • 리덕스 전역 상태를 React 앱 전체에서 사용할 수 있게 만드는 역할
  • store를 하위 컴포넌트에 context로 전달해 줘서, 앱 내 어느 컴포넌트든 useSelector, useDispatch 같은 훅으로 상태에 접근하거나 액션을 보낼 수 있게 함

4. 컴포넌트에서 사용

function App(){
    // state를 사용할때 - useSelector
    // state를 업데이트 - dispatcher

    const count = useSelector(state =>{
        // console.log(state); // 여기서 관리되는 값을 뽑아서 return
        return state.count.value;
    })

    const dispatcher = useDispatch();

    return(

        <>
            <h3>리덕스 예제</h3>
            현재 카운트 : {count}

            <button type='button' onClick={()=>dispatcher( increase() )}>증가</button>
            <button type='button' onClick={()=>dispatcher( decrease() )}>감소</button>
            <Child/>
        </>
    )
}

export default App;
  • useSelector : state를 사용할 때 사용하며 state.(store에 저장한 키값) 형태로 사용
  • useDispatch : state값을 변경할 때 사용하며 선언한 함수명 안에 매개값으로 slice의 함수를 호출하면됨

4-1. 자식요소 컴포넌트에서 사용

function Child(){


    
    const count = useSelector( state => state.count.value);
    const dispatch = useDispatch();

    // 추가된 리듀서
    const [text,setText] = useState('');
    const name = useSelector(state=>state.user.name);
    return (
        <>
            <h3>자식 컴포넌트</h3>

            현재 카운트 : {count}

            <button type='button' onClick={() => dispatch(increase())}>증가</button>
            <button type='button' onClick={() => dispatch(decrease())}>감소</button>

            <h3>새로운 리덕스 상태변수</h3>
            <input type = "text" onChange={e=>setText(e.target.value)} value={text}/>
            <button type='button' onClick={()=>dispatch(setName(text))}>저장</button>
            <br/>
            현재 이름 : {name}
        </>
    )
}

export default Child;