728x90
반응형
반응형
useReducer 사용하기
reducer 함수 생성
올수 있는 액션객체를 유니언 타입으로 쭉 나열
type Action = {type: 'INCREASE'} | {type: 'DECREASE'}
function reducer(state: number, action: Action): number {
//카운터를 바꿀거기때문에 상태하고 리턴값 타입은 number
}
연습해보기 실습
App.tsx
import React from "react";
import ReducerSample from "./components/ReducerSample";
function App() {
return (
<div className="App">
<ReducerSample />
</div>
);
}
export default App;
components폴더안에
ReducerSample.tsx
///리듀서 연습을 위해서 만듬
import React, { useReducer } from 'react';
//color를 타입으로 지정
type Color = 'red' | 'pink' | 'yellow';
//상태타입 지정
type State = {
count: number;
text: string;
color: Color;
isGood: boolean
}
//액션타입 지정
type Action = {type: 'SET_COUNT'; count: number}
| {type: 'SET_TEXT'; text: string}
| {type: 'SET_COLOR'; color: Color}
| {type: 'SET_GOOD'}
//매개변수는 타입지정!!!
//리턴값이 있는 경우 리턴값의 타입을 지정
function reducer(state: State, action: Action) : State{ //reducer는 새로운 상태를 리턴해줌!!! 리턴값 있음
switch(action.type){
case "SET_COUNT":
return {
...state,
count: action.count
}
case "SET_COLOR":
return {
...state,
color: action.color
}
case "SET_TEXT":
return {
...state,
text: action.text
}
case "SET_GOOD":
return {
...state,
isGood: !state.isGood
}
default:
return state;
}
}
const ReducerSample = () => {
const [state, dispatch] = useReducer(reducer, {
count:0,
text: "green",
color: "pink",
isGood: true
})
const setCount = () => {
dispatch({type: "SET_COUNT", count: 5})
}
const setText = () => {
dispatch({type: "SET_TEXT", text: "blue"})
}
const setColor = () => {
dispatch({type: "SET_COLOR", color: "yellow"})
}
const setToggle = () => {
dispatch({type: "SET_GOOD"})
}
return (
<div>
<p>count: {state.count}</p>
<p>text: {state.text }</p>
<p>color: {state.color}</p>
<p>isGood: {state.isGood ? "true": "false"}</p>
<div>
<button onClick={setCount}>SET_COUNT</button>
<button onClick={setText}>SET_TEXT</button>
<button onClick={setColor}>SET_COLOR</button>
<button onClick={setToggle}>SET_ISGOOD</button>
</div>
</div>
);
};
export default ReducerSample;
todolist 실습
App.tsx
import React, { useReducer } from 'react';
import './App.css';
import InputTodo from './components/InputTodo';
import TodoLists from './components/TodoLists';
const initialState = [
{
id: 1,
text: "이력서, 자소서 쓰기",
isDone: false
},
{
id: 2,
text: "이력서, 자소서 쓰기",
isDone: false
},
{
id: 3,
text: "이력서, 자소서 쓰기",
isDone: false
}
]
type Action = "ADDTODO"| "DELTODO"| "TOGGLETODO"
interface actionType {
type: Action;
todo?: dataType;
id? : number;
}
export interface dataType {
id: number;
text: string;
isDone: boolean;
}
function reducer(state: dataType[], action: actionType): dataType[] {
switch(action.type){
case "ADDTODO":
return [
...state,
action.todo! //!는 null과 undefiend가 오지 않는다는 의미 값이 무조건 온다
];
case "DELTODO":
return (state as Array<dataType>).filter(li=>li.id !== action.id);
case "TOGGLETODO":
return (state as Array<dataType>).map(li=> li.id === action.id ? {
//인터페이스를 만들어주고 state는 array<datatype>이라고 지정
...li, isDone: !li.isDone}: li)
default:
return state;
}
}
function App() {
const [todos, dispatch] = useReducer(reducer, initialState)
console.log(todos)
const onAdd = (todo:dataType) => {
dispatch({
type: "ADDTODO",
todo: todo
})
}
const onToggletodo = (id:number) => {
dispatch({type: "TOGGLETODO", id: id})
}
const onDeltodo = (id:number) => {
dispatch({type:"DELTODO", id: id})
}
return (
<div className="App">
<InputTodo onAdd={onAdd}/>
<TodoLists todos={todos}
onToggletodo = {onToggletodo}
onDeltodo = {onDeltodo}/>
</div>
);
}
export default App;
components 폴더 생성
InputTodo.tsx
import React, { useRef, useState } from 'react';
import { dataType } from '../App';
interface InputProps {
onAdd: (todo:dataType) => void
}
const InputTodo = ({onAdd}: InputProps) => {
const [todoState, setTodoState] = useState("")
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
console.log(e)
setTodoState(e.target.value)
}
const todoid = useRef(4) //객체를 리턴해줌 {current : 4}
const onClick = () =>{
onAdd({
id: todoid.current,
text: todoState,
isDone: false
})
setTodoState("")
todoid.current++;
}
return (
<div>
<input name="name" value={todoState} onChange={onChange}/>
<button onClick={onClick}>등록</button>
</div>
);
};
export default InputTodo;
TodoLists.tsx
import React from 'react';
import { dataType } from '../App';
interface todoProps {
todos: dataType[]
onToggletodo: (id:number)=>void
onDeltodo: (id:number)=> void
}
const TodoLists = ({todos, onToggletodo, onDeltodo}: todoProps) => {
return (
<div>
<ul>
{todos.map(todo =><li key={todo.id}
style={{background: todo.isDone ? "yellow" : undefined, listStyle: "none"}}>
<span onClick={()=>{onToggletodo(todo.id)}}>{todo.text}</span>
<button onClick={()=>{onDeltodo(todo.id)}}>삭제</button></li>)}
</ul>
</div>
);
};
export default TodoLists;
728x90
반응형
'typescript' 카테고리의 다른 글
[typescript] as & ReturnType (0) | 2023.02.24 |
---|---|
[typescript] react-typscript(useReducer + contextAPI) (0) | 2023.02.24 |
[typescript]react - typescript(설치, useState) (0) | 2023.02.24 |
[typescript] class 접근제한자, 정적멤버(static), 추상클래스(abstract) (0) | 2023.02.24 |
[typescrip] Generic(제네릭) (1) | 2023.02.24 |
댓글