Dispatch(Action) 👉 Reducer(state,Action)
Dispatch로 Action을 전달하면 state 및 Action을 받은 Reducer가 호출된다.
이 Reducer가 받아온 값을 통하여 state를 업데이트 시켜준다.
Dispatch
reducer를 호출하기 위하여 거쳐야하는 함수
정보는 Action객체를 이용하여 전달한다.
Reducer
state를 업데이트 위하여 거쳐야하는 함수
dispatch를 통해 호출되어 state 및 Action을 매개변수로 받아온다.
state
여러개의 상태값을 관리해야할 때 사용한다.
const [A,dispatch]= useReducer(함수명B,초기값)
👉 return[A, dispatch]
// 1️⃣ A라는 변수를 가지는 state를 작성한다.
function 함수명B(state,action){
switch(action.type){
case "타입명":
return '타입이 "타입명"일때 실행 되어 상태가 될 구문';
}
}
// 2️⃣ "타입명"에 따른 결과를 작성한다.
// 함수명B는 reducer로, dispatch를 통해 호출되어 state및 Action을 매개변수로 받아온다.
dispatch({type:"타입명"})
// 3️⃣ dispatch 및 지정한 타입명으로 상태를 호출한다.
기본적인 useReducer 사용법은 위와 같다.
import Header from './components/Header';
import { useReducer } from 'react';
//------------------------state 초기값 설정------------------------//
const initialState={
input:"",
todos:[
{id:1, text:"내용1", isDone: false},
{id:2, text:"내용2", isDone: false},
],
id: 3
}
//------------------------reducer 함수 선언------------------------//
function reducer(state,action){
switch (action.type) {
case 'addTodo': //할일 추가
return {
...state,
todos: [...state.todos, action.todo],
id: state.id+1,
input: ""
}
case 'changeInput': //input값 변경
return {
...state,
input: action.payload
}
default:
return state;
}
}
//------------------------state 요청------------------------//
function App() {
// 상태 선언하기
const [state,dispatch]= useReducer(reducer,initialState)
const {todos, input, id}= state;
// input update 요청
const onChange=(e)=>{
dispatch({type: 'changeInput', payload: e.target.value})
};
// 할일 항목 추가 update 요청
const addTodo = ()=>{
dispatch({
type:'addTodo',
todo: {id:id,text:input,isDone:false}
})
};
//------------------------return------------------------//
return (
<div className="App">
<Header input={input} onChange={onChange} addTodo={addTodo}/>
</div>
);
}
export default App;
import React from 'react';
const Header = ({input,onChange,addTodo}) => {
return (
<>
<input value={input} onChange={onChange}/>
<button onClick={addTodo}>+</button>
</>
);
};
export default Header;
axios를 이용하여 useReducer를 전역에서 사용 할 수 있도록 작성한다.
import { useEffect, useReducer } from "react"
// 초기값 지정
const initialState={
users: null,
loading: false,
error: null
}
// reducer 함수 및 type 지정
function reducer(state,action){
switch (action.type) {
case 'users':
return{...state, users:action.data, loading: false}
case 'loading':
return{...state, loading: true}
case 'error':
return{...state, error: action.payload}
default:
break;
}};
// 매개변수로 callback 및 deps 받아오는 함수 useAsync 생성
const useAsync = (callback,deps=[]) => {
const [state,dispatch]= useReducer(reducer,initialState)
// useReducer를 사용하여 상태와 상태를 업데이트해줄 dispatch 함수를 받아옴
const fetchUsers= async()=>{
try{
dispatch({type: 'loading'})
const response= await callback();
dispatch({type: 'users', data: response.data})
}
catch(e){
dispatch({type: 'error', payload: e})
}
}
useEffect(()=>{
fetchUsers();
},deps)
// 페이지가 처음 실행 될 때 fetchUsers()를 한번 실행시키고,
// deps가 변경되면 fetchUsers()를 실행시킨다.
return [state,fetchUsers];
// 아래 Users함수에서 사용된다.
};
export default useAsync;
import axios from 'axios';
import React from 'react';
import useAsync from '../hooks/useAsync';
async function getUsers(){
const response= await axios.get(
'//jsonplaceholder.typicode.com/users'
)
return response;
};
// Users의 callback으로 들어갈 값(주소값)을 지정
const Users = () => {
const [state,refetch]=useAsync(getUsers,[])
// useAsync 함수에서 return된 [state,fetchUsers]를 담았다
// state는 초기값 initialState을 기반으로 바뀌는 상태이다.
// refetch는 상황에 따라 state를 바꾸는 함수이다.
const {users, loading, error}= state;
if(loading) return <div>로딩중...</div>
if(error) return <div>에러가 발생했습니다.</div>
if(!users) return null;
return (
<div>
<ul>
{users.map(user=><li key={user.id}>{user.username} {user.name}</li>)}
</ul>
<button onClick={refetch}>재요청</button>
</div>
);
};
export default Users;