Context API 탐방기 - 4

J-USER·2021년 6월 3일
0

ContextAPI

목록 보기
5/6
post-thumbnail

( ⚠️ 이 포스팅은 이전 포스팅에 이어진 내용 입니다. )

0️⃣ 들어가기 앞서

이전 포스팅에서 context 를 만들고 각각 context에 있는 값을 변경하기 위해 함수를 작성했었습니다.

예를 들어 A context 에 있는 state(값)를 바꾸기 위해 A'라는 함수를 작성하고, B context 에 값을 변경하기 위해 B' 함수를 만들었다고 가정합시다!

그러면 자연스럽게 만약 데이터가 아주아주 많고 다양하다면 ? 🤔

우리가 context를 나눴던 이유는 각각의 값들의 속성의 성격?종류? 가 다르기 때문에 나눴습니다. 그러나... 우리는 생각합니다..

😈 : context가 100개가 있고 만약 각각 다뤄야할 값이 100개라면 어쩔껀데???
🥲 : 저한테 왜그러세요..

만약 이전 포스팅과 같이 코딩을 했다면 각각의 context의 state 변경 함수를 알기위해 들어가서 필요한것을 찾고... 아무튼 복잡함! 🔥

이를 방지하고 간단히하기 위해 하나의 함수에서 상태와 원하는 액션을 하게 만들어주면 됩니다. 그렇게 나온 개념이 Reducer 입니다.

정의 하자면 Reducer = useState를 사용하지 않고 상태를 관리하게 해줌 + 상태 업데이트 로직의 분리.

function reducer(state, action) {
  // 새로운 상태를 만드는 로직
  // 말은 어려워 보이지만 그냥 평범한 함수랑 다름이 없습니다!
  return newState;
}

const [state, dispatch] = useReducer(reducer, initialState);
// dispatch : 액션을 발생시키는 트리거

1️⃣ Reducer 만들어 보기

//bookReducer.js

export const bookReducer = (state,action) =>{
    switch(action.type) { // 이 부분에서 TS와 아주아주 찰떡! 
        case 'ADD_BOOK' : //새로운 북 추가
            return [...state, {
                title : action.book.title,
                author: action.book.author,
                id : uuid()
            }]
        case 'REMOVE_BOOK' : // 북 제거
            return state.filter(book => book.id !== action.id)
        
        default:
            return state
    }
}

2️⃣ 컴포넌트에 적용해보기

👇 리듀서 적용

//BookContext.js
function BookContextProvider(props) {
    const [books, dispatch] = useReducer(bookReducer,[]);
    // (무슨리듀서?,초기dispatch)
    // [사용할 state, 사용할 액션 불러올 commend같은 것]

    /* const [books, setBooks] = useState([
        {title: 'name of the wind', author:'patrick rothfuss',id: 1},
        {title: 'the way of kings', author:'brandon sanderson', id: 2},
    ])

    const addBook = (title,author) =>{
        setBooks([...books,{title,author, id: uuid() }])
    }

    const removeBook = (id) =>{
        setBooks(books.filter(book => book.id !== id))
     }*/ 이전 코드

    return(
        <BookContext.Provider value ={{books, dispatch}}>
            {props.children}
        </BookContext.Provider>
    )
}

👇 사용

//BookForm.js

function NewBookForm() {
    const {dispatch} = useContext(BookContext);
    const [title,setTitle] = useState('');
    const [author,setAuthor] = useState('');
    
    const handleSubmit = (e) =>{
        e.preventDefault()
        // addBook(title,author); 이렇게 함수 쓸게 아니라
        dispatch({type : 'ADD_BOOK', book :{title,author}}); // dispatch로 알려줌
        setTitle('');
        setAuthor('');
    }
    return(
        <form onSubmit={handleSubmit}>
            <input type="text" placeholder="book title" value={title} onChange={(e) => setTitle(e.target.value)} required/>
            <input type="text" placeholder="book author" value={author} onChange={(e) => setAuthor(e.target.value)} required/>
            <input type="submit" value="add book" />
        </form>
    );
}

👇 다른 컴포넌트에도 적용

//BookDetail.js

function BookDetails ({book}) {
    const {dispatch} = useContext(BookContext)

    return(
    <li onClick ={() => dispatch({type: 'REMOVE_BOOK', id: book.id})}>
     {/* <li onClick ={() => removeBook(book.id)}> */}
        <div className ="title"><h4> - {book.title}</h4></div>
        <div className ="author">{book.author}</div>
    </li>)
}

export default BookDetails
profile
호기심많은 개발자

0개의 댓글