관리 메뉴

CASSIE'S BLOG

udemy MOdern React with Redux 본문

PROGRAMMING/React

udemy MOdern React with Redux

ITSCASSIE1107 2023. 6. 20. 12:56

Redux는 기능 구현을 위해 짜야 하는 보일러플레이트 코드가 많았다.

 

일단 Action들을 처리해줄 Reducer를 구성

 

인덱스 파일 안에 앱 구성요소를 표시하고 있는 곳을 찾을 수 있다.
 
앱 구성요소를 래핑할 수 있다. 

이제 앱 구성요소와 그 하위요소 모두가 값 5 프로펄티에 액세스 할 수 있다.
 
<App/>이 안쪽에 있다. 
 
**D:\personal\udemy-modern-react-workspace\002_context\src\index.js

import './index.css';
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import BooksContext from './context/books';

const el = document.getElementById('root');
const root = ReactDOM.createRoot(el);

root.render(
  <BooksContext.Provider value={10}>
    <App />
  </BooksContext.Provider>
);

 
 
**D:\personal\udemy-modern-react-workspace\002_context\src\context\books.js

import './index.css';
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import BooksContext from './context/books';

const el = document.getElementById('root');
const root = ReactDOM.createRoot(el);

root.render(
  <BooksContext.Provider value={10}>
    <App />
  </BooksContext.Provider>
);

 
컨텍스트를 이요해서 다양한 구성 요소 전반에 걸쳐서 정보를 공유할 수 있지만 수동으로 이 값을 바꿔야한다는 장점이 있음
 
 
D:\personal\udemy-modern-react-workspace\002_context\src\context\books.js

import { createContext } from 'react';

const BooksContext = createContext();

export default BooksContext;

 
이걸 이렇게 바꾸면
 

import { createContext, useState } from 'react';

const BooksContext = createContext();

function Provider({children}){
    const [count, setCount] = useState(5);

}

export default BooksContext;

 

 
and then I'm going to show inside their children 

이 코드에서는 we have now created a new component "Provider", and we need to export (엑스폴트) it so we can use it in some other locations.
 
the default export is the context object. 
그래서 그 위에 이렇게 적어줘야함 export {Provider};
 

import { createContext, useState } from 'react';

const BooksContext = createContext();

function Provider({children}){
    const [count, setCount] = useState(5);

    const valueToShare = {
        count,
        incrementCount: () => {
            setCount(count + 1);
        }
    };

    return <BooksContext.Provider value={valueToShare}>
    {children}
    </BooksContext.Provider>
}  

export {Provider};
export default BooksContext;

 

이제 BooksContext를 전부다 import 할 필요가 없다함.book.js 파일에
 
<App /> 이게 중간에 있으면 
the app component is going to show up as a prop to a provider called children
 
그리고 BookList.js파일에서 count, incrementCount 에 접근하려면 destructering 해야된다고함
 
[원본]

import { useContext } from 'react';
import BooksContext from '../context/books';
import BookShow from './BookShow';

function BookList({ books, onDelete, onEdit }) {
  const value = useContext(BooksContext);

  const renderedBooks = books.map((book) => {
    return (
      <BookShow onEdit={onEdit} onDelete={onDelete} key={book.id} book={book} />
    );
  });

  return (
    <div className="book-list">
      {value}
      {renderedBooks}
    </div>
  );
}

export default BookList;

value부분을 이렇게 바꿈
onClick 이벤트 걸고 
 
 

import { useContext } from 'react';
import BooksContext from '../context/books';
import BookShow from './BookShow';

function BookList({ books, onDelete, onEdit }) {
  const {count, incrementCount} = useContext(BooksContext);

  const renderedBooks = books.map((book) => {
    return (
      <BookShow onEdit={onEdit} onDelete={onDelete} key={book.id} book={book} />
    );
  });

  return (
    <div className="book-list">
      {count}
      <button onClick={incrementCount}>Click</button>
      {renderedBooks}
    </div>
  );
}

export default BookList;

이게 현재 entire app
 

 

기억하기
화면에서 컨텐츠가 바뀌는건 어떤 상태가 (state)가 필요하다는 신호다.
 
App의 checkInDate, checkOutDate는 데이터 페치 과정의 일부에서 사용할려면 필요하다. 
따라서 날짜 선택기 구성 요소는 어떤 상태 조각이 필요하다 날짜가 열렸는지 닫혔는지 계속 추적하려면요.
 

 
 
**book.js 수정함 그 카운터 부분 다 지움
 
 

import { createContext, useState } from 'react';

const BooksContext = createContext();

function Provider({children}){
 

    return <BooksContext.Provider value={{}}>
    {children}
    </BooksContext.Provider>
}  

export {Provider};
export default BooksContext;

 
**bookList.js도 수정함
 

import { useContext } from 'react';
import BooksContext from '../context/books';
import BookShow from './BookShow';

function BookList({ books, onDelete, onEdit }) {


  const renderedBooks = books.map((book) => {
    return (
      <BookShow onEdit={onEdit} onDelete={onDelete} key={book.id} book={book} />
    );
  });

  return (
    <div className="book-list">
   
      {renderedBooks}
    </div>
  );
}

export default BookList;

 
app.js의 부분을.... 없애서 book.js로 옮김 이거 원본
 
 

import { useState, useEffect } from 'react';
import axios from 'axios';
import BookCreate from './components/BookCreate';
import BookList from './components/BookList';

function App() {
  const [books, setBooks] = useState([]);

  const fetchBooks = async () => {
    const response = await axios.get('http://localhost:3001/books');

    setBooks(response.data);
  };

  useEffect(() => {
    fetchBooks();
  }, []);

  const editBookById = async (id, newTitle) => {
    const response = await axios.put(`http://localhost:3001/books/${id}`, {
      title: newTitle,
    });

    const updatedBooks = books.map((book) => {
      if (book.id === id) {
        return { ...book, ...response.data };
      }

      return book;
    });

    setBooks(updatedBooks);
  };

  const deleteBookById = async (id) => {
    await axios.delete(`http://localhost:3001/books/${id}`);

    const updatedBooks = books.filter((book) => {
      return book.id !== id;
    });

    setBooks(updatedBooks);
  };

  const createBook = async (title) => {
    const response = await axios.post('http://localhost:3001/books', {
      title,
    });

    const updatedBooks = [...books, response.data];
    setBooks(updatedBooks);
  };

  return (
    <div className="app">
      <h1>Reading List</h1>
      <BookList onEdit={editBookById} books={books} onDelete={deleteBookById} />
      <BookCreate onCreate={createBook} />
    </div>
  );
}

export default App;

 
app.js  다 자르고 밑에

      <BookList  />
      <BookCreate/>

 

이 부분도 다 지워줌 prop

앱구성요소를 컨텍스트에 도달하려면 import useContext 해야함

App.js에서 import BooksContext from './context/books';하고

function App() {
useContext(BooksContext); 
이거 하면 
우리가 공유하고자하는 전체 개체를 제공하는거죠.

 

 
 
import {  useEffect, useContext } from 'react';
import BookCreate from './components/BookCreate';
import BookList from './components/BookList';
import BooksContext from './context/books'


function App() {
  const {fetchBooks} = useContext(BooksContext);
 

  useEffect(() => {
    fetchBooks();
  }, []);

 
  return (
    <div className="app">
      <h1>Reading List</h1>
      <BookList  />
      <BookCreate/>
    </div>
  );
}

export default App;

By using object destructuring with {}, you can directly assign the fetchBooks function to the fetchBooks variable.

{}중괄호 안에 props.전달할 값 을 입력해준다.
{{}}중괄호를 두번 감싸준 이유는 괄호 안 자바스크립트 값을 객체로 보겠다는 의미.
 
Axios는 브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리 아다. 쉽게 말해서 백엔드랑 프론트엔드랑 통신을 쉽게하기 위해 Ajax와 더불어 사용한다.
 
App.js에서 axis를 book.js에 옮기고, useState import 없애고 
 
book.js에서 const valueToShare 만든다.
 
it will become inside this object. 

books:books - > books로 줄일 수 있음
 
수정한 book.js

import { createContext, useState } from 'react';
import axios from 'axios';

const BooksContext = createContext();

function Provider({children}){

    const [books, setBooks] = useState([]);

    const fetchBooks = async () => {
    const response = await axios.get('http://localhost:3001/books');

    setBooks(response.data);
  };
 


  const editBookById = async (id, newTitle) => {
    const response = await axios.put(`http://localhost:3001/books/${id}`, {
      title: newTitle,
    });

    const updatedBooks = books.map((book) => {
      if (book.id === id) {
        return { ...book, ...response.data };
      }

      return book;
    });

    setBooks(updatedBooks);
  };

  const deleteBookById = async (id) => {
    await axios.delete(`http://localhost:3001/books/${id}`);

    const updatedBooks = books.filter((book) => {
      return book.id !== id;
    });

    setBooks(updatedBooks);
  };

  const createBook = async (title) => {
    const response = await axios.post('http://localhost:3001/books', {
      title,
    });

    const updatedBooks = [...books, response.data];
    setBooks(updatedBooks);
  };



    const valueToShare = {
        books,
        deleteBookById,
        editBookById,
        createBook,
        fetchBooks

    }

    return <BooksContext.Provider value={valueToShare}>
    {children}
    </BooksContext.Provider>
}  

export {Provider};
export default BooksContext;

 


 
--아무것도 안한 Bookcreate.js
 

import { useState } from 'react';

function BookCreate({ onCreate }) {
  const [title, setTitle] = useState('');

  const handleChange = (event) => {
    setTitle(event.target.value);
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    onCreate(title);
    setTitle('');
  };

  return (
    <div className="book-create">
      <h3>Add a Book</h3>
      <form onSubmit={handleSubmit}>
        <label>Title</label>
        <input className="input" value={title} onChange={handleChange} />
        <button className="button">Create!</button>
      </form>
    </div>
  );
}

export default BookCreate;

컨텍스트에 접근해서 Provider에있는 createBook 북생성기능에 엑세스를 하려고 함
 

1. userContext import 
2. 다른 디렉토라에서 BooksContext 가져오기
3. 이제 컨텍스트 객체로 가서 create book 기능을 불러올게요 (전체 컨텍스트개체에서 원하는 유일한 기능) 
    const {createBook} = useContext(BooksContext);
4. 이제 onCreate prop 안 써서 매개변수 지우기 
5. handleSubmit = () => {} 여기서 
  onCreate(title); 이거 - > createBook(title); 로 바꾸기
 
리팩토링한  Bookcreate.js

import { useState, useContext } from 'react';
import BooksContext from '../context/books';

function BookCreate({}) {
  const [title, setTitle] = useState('');
  const {createBook} = useContext(BooksContext);

  const handleChange = (event) => {
    setTitle(event.target.value);
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    createBook(title);
    setTitle('');
  };

  return (
    <div className="book-create">
      <h3>Add a Book</h3>
      <form onSubmit={handleSubmit}>
        <label>Title</label>
        <input className="input" value={title} onChange={handleChange} />
        <button className="button">Create!</button>
      </form>
    </div>
  );
}

export default BookCreate;

 
 
 
 
bookList 수정 전 리팩토링 중 
 

import { useContext } from 'react';
import BooksContext from '../context/books';
import BookShow from './BookShow';

function BookList({ books, onDelete, onEdit }) {


  const renderedBooks = books.map((book) => {
    return (
      <BookShow onEdit={onEdit} onDelete={onDelete} key={book.id} book={book} />
    );
  });

  return (
    <div className="book-list">
   
      {renderedBooks}
    </div>
  );
}

export default BookList;

 

1. const {books} = useContext(BooksContext); 
2. I'm then going to tell Booklist that's no longer going to receive these props. { books, onDelete, onEdit } 매개변수 중괄호까지 다 삭제 
3.   <BookShow onEdit={onEdit} onDelete={onDelete} key={book.id} book={book} /> 에서 onEdit 부분 삭제 지웠으니까 
4. remember 하라는데 wehn we start making use of context, we still use props. 그래서 books = {books} 를 지우면 안된다는 말을 하고싶어하는 것 같은데? 
"We still make use of props, even if we are using context"
 


처리하기전 bookEdit.js
 

import { useState } from 'react';

function BookEdit({ book, onSubmit }) {
  const [title, setTitle] = useState(book.title);

  const handleChange = (event) => {
    setTitle(event.target.value);
  };

  const handleSubmit = (event) => {
    event.preventDefault();

    onSubmit(book.id, title);
  };

  return (
    <form onSubmit={handleSubmit} className="book-edit">
      <label>Title</label>
      <input className="input" value={title} onChange={handleChange} />
      <button className="button is-primary">Save</button>
    </form>
  );
}

export default BookEdit;

 
매개변수 지우고, 뭐 난리다
수정 후
 
 

 
import { useState, useContext } from 'react';
import BooksContext from '../context/books';

function BookEdit({ book, onSubmit }) {
  const [title, setTitle] = useState(book.title);
  const {editBookById} = useContext(BooksContext);

  const handleChange = (event) => {
    setTitle(event.target.value);
  };

  const handleSubmit = (event) => {
    event.preventDefault();

    onSubmit();
    editBookById(book.id, title);
  };

  return (
    <form onSubmit={handleSubmit} className="book-edit">
      <label>Title</label>
      <input className="input" value={title} onChange={handleChange} />
      <button className="button is-primary">Save</button>
    </form>
  );
}

export default BookEdit;

useShow부분도 수정함 
140번 강의 정리하기

서버 에러나는데 서버를 만든적이 없다니가? 아닌가?


반응형