Context API 탐방기 - 3

J-USER·2021년 6월 1일
0

ContextAPI

목록 보기
4/6
post-thumbnail

( ⚠️ 이전 포스팅에서 이어지는 내용입니다 )

🔥 들어가기에 앞서

이전 포스팅에서 하게 될 내용은 이전 포스팅에서 했던 context의 생성, 수정을 통해 자식 노드에 변경 사항을 적용하는 기능에 대해 알아보았습니다.

그런데 만약 엄청나게 많은 데이터가 context에 들어가게 되면 어떡할까? 물론 복잡해 질것이고 이는 곧 개발자의 혼란으로 이어지게 되고... 이는 곧 낮은 퀄리티의 결과로 이어지게 됩니다...

그래서 이번 포스팅에서는 다중 context를 생성하고 이를 하위 노드에서 접근하고, 수정하는 기능을 추가해 볼 예정입니다.

한줄 요약 👉 게시판 만들거임 ㅎ

1️⃣ 다중 창고 생성 및 접근

👇 먼저 AuthContext 를 새롭게 만들어 줍니다.

// AuthContext.js 

export const AuthContext = createContext(); // ThemeContext 외의 다른 context 생성.

function AuthContextProvider (props) {
    const [state,setState] = useState({
        isAuthenticated: false 
    })
    // 기본값 설정
    const toggleAuth = () =>{
        setState({isAuthenticated : !state.isAuthenticated})
    }
	// 수정 함수 작성
    return(
        <AuthContext.Provider value={{...state,toggleAuth: toggleAuth}}> // 값 넘겨줌
            {props.children} // 모든 자식에게 이용권한 줌.
        </AuthContext.Provider>
    )
}

export default AuthContextProvider

👇 아래와 같이 App에서 새로 생성한 context도 적용시켜줌.

//App.js

function App() {
  return (
    <div className="App">
      <ThemeContextProvider>
        
        <AuthContextProvider>

          <Navbar />
          <ThemeToggle/>

        </AuthContextProvider>
        
      </ThemeContextProvider>
    </div>
  );
}

👇 하위 노드에서 접근하는 것은 이전 포스팅과 마찬가지로 2 가지가 있습니다. useContext 사용 or Consumer 사용..아래 코드는 Consumer을 사용한 접근입니다.

// Navbar.js
...

function Navbar () {
    return (
    //요로코롬 마치 2중 for문을 연상 시키듯이 해줌..
    
      <AuthContext.Consumer>{(authContext) => (
        <ThemeContext.Consumer>{(context) =>{
          const { isAuthenticated , toggleAuth} = authContext
          const { isLightTheme, light, dark } = context;
          const theme = isLightTheme ? light : dark;
          return(
            <nav style={{background: theme.ui, color: theme.syntax }}>
              <h1>Context App</h1>
              <div onClick ={toggleAuth}>
                {isAuthenticated ? 'Logged in' : 'Logged out '}
              </div>
              <ul>
                <li>Home</li>
                <li>About</li>
                <li>Contact</li>
              </ul>
            </nav>
          )
        }}
        </ThemeContext.Consumer>
      )}
      </AuthContext.Consumer>
    );

}

export default Navbar;

2️⃣ 게시판 만들기

👇 게시판 역할을 할 BookContext를 새롭게 만들어 줍니다

//BookContex.Js

import uuid from 'uuid/v1'

export const BookContext = createContext();

function BookContextProvider(props) {
    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() }])
    }
    // book 정보를 추가 시켜줌 ( add )

    const removeBook = (id) =>{
        setBooks(books.filter(book => book.id !== id))
    }
	// book 정보를 삭제해줌 ( del )
    return(
        <BookContext.Provider value ={{books, addBook, removeBook}}>
            {props.children}
        </BookContext.Provider>
    )
}

export default BookContextProvider

👇 BookContext에 있는 값을 표현해줌

// BookList

function BookList () { 
  const {isLightTheme , light, dark} = useContext(ThemeContext)
  const { books } = useContext(BookContext)
  const theme = isLightTheme ? light : dark;

    return books.length ? ( 
      <div className="book-list" style={{color : theme.syntax, background : theme.bg}}>
        <ul>
          {books.map(book =>{
            return(
              <BookDetails book={book} key = {book.id}/>    
            )
          })}
        </ul>
      </div>
    ) : (
      <div className ="empty">
          No books to read. Hello free time :) 
      </div>
    );
}

👇 BookContext 값 표현

// BookDetails
function BookDetails ({book}) {
    const {removeBook} = useContext(BookContext)

    return(
    <li onClick ={() => removeBook(book.id)}>
        <div className ="title"><h4> - {book.title}</h4></div>
        <div className ="author">{book.author}</div>
    </li>)
}

export default BookDetails

👇 Book 추가 해주는 컴포넌트 작성

// NewBookForm 
function NewBookForm() {
    const {addBook} = useContext(BookContext);
    const [title,setTitle] = useState(''); 
    const [author,setAuthor] = useState('');
    
    const handleSubmit = (e) =>{
        e.preventDefault()
        addBook(title,author); // 컨텍스트에 book 추가해줌
        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>
    );
}

👇 모두 한곳에 모아줌

function App() {
  return (
    <div className="App">
      <ThemeContextProvider>
        
        <AuthContextProvider>

          <Navbar />
          <BookContextProvider>
            <BookList />
            <NewBookForm/>
          </BookContextProvider>
          <ThemeToggle/>

        </AuthContextProvider>
        
      </ThemeContextProvider>
    </div>
  );
}

3️⃣ 결과

👇 원래 모습

👇 항목을 선택하게 되면,

👇 새로운 책 추가

profile
호기심많은 개발자

0개의 댓글