useState에서 배열을 사용하는 학습 선행 필요
https://velog.io/@wotjr294/useState-Object
import React from 'react';
import { data } from '../../../data';
const ReducerBasics = () => {
const [people, setPeople] = React.useState(data);
const removeItem = (id) => {
let newPeople = people.filter((person) => person.id !== id);
setPeople(newPeople);
};
const clearList = () => {
setPeople([]);
}
const resetList = () => {
setPeople(data);
}
return (
<div>
{people.map((person) => {
const { id, name } = person;
return (
<div key={id} className='item'>
<h4>{name}</h4>
<button onClick={() => removeItem(id)}>remove</button>
</div>
);
})}
{people.length < 1 ?
<button
className='btn'
style={{ marginTop: '2rem' }}
onClick={resetList}
>
Reset
</button>
:
<button
className='btn'
style={{ marginTop: '2rem' }}
onClick={clearList}
>
Clear
</button>
}
</div>
);
};
export default ReducerBasics;
import { useState, useReducer } from 'react';
import { data } from '../../../data';
const defaultState = {
people : data,
isLoading : false,
}
const reducer = (state, action) => {
if(action.type === 'CLEAR_LIST'){
return {...state, people : []};
}
}
const ReducerBasics = () => {
const [state, dispatch] = useReducer(reducer, defaultState)
const removeItem = (id) => {
// let newPeople = people.filter((person) => person.id !== id);
// setPeople(newPeople);
};
const clearList = () => {
dispatch({ type : 'CLEAR_LIST'});
// setPeople([]);
}
const resetList = () => {
// setPeople(data);
}
console.log(state)
return (
<div>
{state.people.map((person) => {
const { id, name } = person;
return (
<div key={id} className='item'>
<h4>{name}</h4>
<button onClick={() => removeItem(id)}>remove</button>
</div>
);
})}
{state.people.length < 1 ?
<button
className='btn'
style={{ marginTop: '2rem' }}
onClick={resetList}
>
Reset
</button>
:
<button
className='btn'
style={{ marginTop: '2rem' }}
onClick={clearList}
>
Clear
</button>
}
</div>
);
};
export default ReducerBasics
💡 useReducer의 주요 개념
- State 와 Dispatch
useReducer는 두 가지 값을 반환한다. 첫 번째는 현재 상태(state), 두 번째는 상태를 업데이트하는 함수(dispatch)이다.- 초기 상태와 리듀서 함수
useReducer 를 사용할 때는 초기 상태와 리듀서 함수를 함께 제공한다. 초기 상태는 상태의 초기값을 나타내며, 리듀서 함수는 상태를 어떻게 업데이트할지에 대한 로직을 담고 있는 함수이다.- 액션(Action)
dispatch 함수를 호출할 때 사용되는 객체로, 최소한 type속성을 가지고 있어야 한다. type은 어떤 종류의 액션을 수행할 것인지를 나타낸다.- 리듀서 함수
현재 상태(state)와 액션(action)을 받아서 새로운 상태를 반환하는 함수이다. 액션의 타입에 따라 다양한 로직을 수행할 수 있다.const [state, dispatch] = useReducer(reducer, initialState);
import { useState, useReducer } from 'react';
import { data } from '../../../data';
const defaultState = {
people : data,
isLoading : false,
}
const CLEAR_LIST = 'CLEAR_LIST';
const RESET_LIST = 'RESET_LIST';
const REMOVE_LIST = 'REMOVE_ITEM';
const reducer = (state, action) => {
if(action.type === CLEAR_LIST){
return {...state, people : []};
}
if (action.type === RESET_LIST){
return {...state, people : data}
}
throw new Error(`No matching "${action.type}" - action type`)
}
const ReducerBasics = () => {
const [state, dispatch] = useReducer(reducer, defaultState)
const removeItem = (id) => {
// let newPeople = people.filter((person) => person.id !== id);
// setPeople(newPeople);
};
const clearList = () => {
dispatch({ type : CLEAR_LIST });
}
const resetList = () => {
dispatch({type : RESET_LIST})
}
console.log(state)
return (
<div>
{state.people.map((person) => {
const { id, name } = person;
return (
<div key={id} className='item'>
<h4>{name}</h4>
<button onClick={() => removeItem(id)}>remove</button>
</div>
);
})}
{state.people.length < 1 ?
<button
className='btn'
style={{ marginTop: '2rem' }}
onClick={resetList}
>
Reset
</button>
:
<button
className='btn'
style={{ marginTop: '2rem' }}
onClick={clearList}
>
Clear
</button>
}
</div>
);
};
export default ReducerBasics;
액션 type 값을 전역 변수로 지정하여 실수를 방지하고, reducer를 처리하는 함수에서 type값에 대한 상태 관리 처리가이루어지지 않은 경우 에러처리를 하였다
import { useState, useReducer } from 'react';
import { data } from '../../../data';
const defaultState = {
people : data,
isLoading : false,
}
const CLEAR_LIST = 'CLEAR_LIST';
const RESET_LIST = 'RESET_LIST';
const REMOVE_ITEM = 'REMOVE_ITEM';
const reducer = (state, action) => {
if(action.type === CLEAR_LIST){
return {...state, people : []};
}
if (action.type === RESET_LIST){
return {...state, people : data}
}
if (action.type === REMOVE_ITEM){
let newPeople = state.people.filter((person) => person.id !== action.payload.id);
return {...state, people : newPeople};
}
throw new Error(`No matching "${action.type}" - action type`)
}
const ReducerBasics = () => {
const [state, dispatch] = useReducer(reducer, defaultState)
const removeItem = (id) => {
dispatch({type : REMOVE_ITEM, payload: {id}})
};
const clearList = () => {
dispatch({ type : CLEAR_LIST });
}
const resetList = () => {
dispatch({type : RESET_LIST})
}
console.log(state)
return (
<div>
{state.people.map((person) => {
const { id, name } = person;
return (
<div key={id} className='item'>
<h4>{name}</h4>
<button onClick={() => removeItem(id)}>remove</button>
</div>
);
})}
{state.people.length < 1 ?
<button
className='btn'
style={{ marginTop: '2rem' }}
onClick={resetList}
>
Reset
</button>
:
<button
className='btn'
style={{ marginTop: '2rem' }}
onClick={clearList}
>
Clear
</button>
}
</div>
);
};
export default ReducerBasics;
useReducer 함수 설정
const initialState = {
// 초기 상태 정의
};
const reducer = (state, action) => {
// 액션에 따른 상태 업데이트 로직 정의
};
useReducer 를 호출하여 현재 상태(state)와 액션을 디스패치하는 함수(dispatch)를 생성
const [state, dispatch] = useReducer(reducer, initialState);
액션 객체를 생성하고 dispatch 함수를 사용하여 리듀서에게 액션을 전달
const action = {
type: 'SOME_ACTION',
payload: 'some data',
};
dispatch(action);
리듀서 함수에서 액션의 type을 기반으로 상태를 업데이트하는 로직을 작성
const reducer = (state, action) => {
switch (action.type) {
case 'SOME_ACTION':
// 액션 타입에 따른 상태 업데이트 로직
return { ...state, someProperty: action.payload };
// 다른 액션에 대한 처리...
default:
return state;
}
};
리듀서에서 반횐된 새로운 상태가 useReducer에 의해 현재 상태로 갱신
const [state, dispatch] = useReducer(reducer, initialState);
action.js 생성
모든 action 복사
export/import action
reducer.js 생성
import action
import data
export/import reducer
import { useState, useReducer } from 'react';
import { data } from '../../../data';
import { CLEAR_LIST, RESET_LIST, REMOVE_ITEM } from './actions';
import reducer from './reducer';
const defaultState = {
people : data,
isLoading : false,
}
const ReducerBasics = () => {
const [state, dispatch] = useReducer(reducer, defaultState)
const removeItem = (id) => {
dispatch({type : REMOVE_ITEM, payload: {id}})
};
const clearList = () => {
dispatch({ type : CLEAR_LIST });
}
const resetList = () => {
dispatch({type : RESET_LIST})
}
console.log(state)
return (
<div>
{state.people.map((person) => {
const { id, name } = person;
return (
<div key={id} className='item'>
<h4>{name}</h4>
<button onClick={() => removeItem(id)}>remove</button>
</div>
);
})}
{state.people.length < 1 ?
<button
className='btn'
style={{ marginTop: '2rem' }}
onClick={resetList}
>
Reset
</button>
:
<button
className='btn'
style={{ marginTop: '2rem' }}
onClick={clearList}
>
Clear
</button>
}
</div>
);
};
export default ReducerBasics;
actions.js
export const CLEAR_LIST = 'CLEAR_LIST';
export const RESET_LIST = 'RESET_LIST';
export const REMOVE_ITEM = 'REMOVE_ITEM';
reducer.js
import { CLEAR_LIST, RESET_LIST, REMOVE_ITEM } from './actions';
import { data } from '../../../data';
const reducer = (state, action) => {
if(action.type === CLEAR_LIST){
return {...state, people : []};
}
if (action.type === RESET_LIST){
return {...state, people : data}
}
if (action.type === REMOVE_ITEM){
let newPeople = state.people.filter((person) => person.id !== action.payload.id);
return {...state, people : newPeople};
}
throw new Error(`No matching "${action.type}" - action type`)
}
export default reducer;