[React] Redux

Hoya_03ยท2022๋…„ 6์›” 29์ผ
0

ai_School

๋ชฉ๋ก ๋ณด๊ธฐ
24/30
post-thumbnail

๐ŸŽˆ Redux

๐ŸŽŠ ๊ฐœ๋…

  • JavaScript ์ƒํƒœ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

Node.js ๋ชจ๋“ˆ
์ƒํƒœ๊ด€๋ฆฌ ํˆด ์ข…๋ฅ˜: React Context, Redux, Mobx
-JavaScript ์ƒํƒœ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

Node.js ๋ชจ๋“ˆ
์ƒํƒœ๊ด€๋ฆฌ ํˆด ์ข…๋ฅ˜: React Context, Redux, Mobx

๐ŸŽŠ ์ƒํƒœ๊ด€๋ฆฌ ํ•„์š”์„ฑ

  • ์ƒํƒœ๊ด€๋ฆฌ

    React์—์„œ State๋Š” component ์•ˆ์—์„œ ๊ด€๋ฆฌ๋˜๋Š” ๊ฒƒ

  • Component๊ฐ„์˜ ์ •๋ณด ๊ณต์œ 
    ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋“ค ๊ฐ„์˜ ๋‹ค์ด๋ ‰ํŠธ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์€ ๋ถˆ๊ฐ€๋Šฅ
    ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋“ค ๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›์„ ๋•Œ๋Š” ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ด์„œ ์ฃผ๊ณ  ๋ฐ›์Œ.
    ์ž์‹์ด ๋งŽ์•„์ง€๋ฉด ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ๋งค์šฐ ๋ณต์žกํ•ด์ง.
    ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ณ„์† ๋‚ด๋ ค ๋ฐ›์•„์•ผ ํ•จ.
    -> Props drilling ์ด์Šˆ

    ์ „์—ญ ์ƒํƒœ ์ €์žฅ์†Œ๊ฐ€ ์žˆ๊ณ , ์–ด๋””์„œ๋“  ํ•ด๋‹น ์ €์žฅ์†Œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋ฌธ์ œ ํ•ด๊ฒฐ

๐ŸŽŠ ๊ตฌ์„ฑ

  • Provider๋ž€?
    Provider์€ react-redux ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์•ˆ์— ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ
    ๋ฆฌ์•กํŠธ ์•ฑ์— ์Šคํ† ์–ด๋ฅผ ์‰ฝ๊ฒŒ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ์ปดํฌ๋„ŒํŠธ

  • combineReducer๋ž€?
    redux๋ชจ๋“ˆ์ด ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜
    ๋งŒ๋“  ๋ชจ๋“  ๋ฆฌ๋“€์„œ๋“ค์„ ํ†ตํ•ฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ๋ฆฌ๋“€์„œ๋กœ ์“ฐ๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜

  • useSelector๋ž€?
    redux์˜ state์กฐํšŒ (์ฆ‰, ์Šคํ† ์–ด์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋“ค ์กฐํšŒ)

  • useDispatch๋ž€?
    ์ƒ์„ฑํ•œ action ์‹คํ–‰

์‹คํ–‰

npm install redux react-redux

์‹ค์Šต

App.js

import logo from './logo.svg';
import './App.css';
import {Container, Row, Col} from 'react-bootstrap';
import ContactForm from './components/ContactForm';
import ContactList from './components/ContactList';
import 'bootstrap/dist/css/bootstrap.min.css'

function App() {
  return (
    <div className="App">
      <h1 className = "title">์—ฐ๋ฝ์ฒ˜</h1>
      <Container>
        <Row>
          <Col>
            <ContactForm></ContactForm>
          </Col>
          <Col>
            <ContactList></ContactList>
          </Col>
        </Row>
        <Row></Row>
      </Container>
    </div>
  );
};

export default App;

ContactForm.js

import React from 'react';
import {Form, Button} from 'react-bootstrap';

const ContactForm = () => {
  return(
    <Form>
      <Form.Group className="mb-3" controlId="formName">
        <Form.Label>์ด๋ฆ„</Form.Label>
        <Form.Control type="text" placeholder="์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”" />
    </Form.Group>

      <Form.Group className="mb-3" controlId="formBasicPassword">
        <Form.Label>Password</Form.Label>
        <Form.Control type="password" placeholder="Password" />
      </Form.Group>
      <Form.Group className="mb-3" controlId="formBasicCheckbox">
        <Form.Check type="checkbox" label="Check me out" />
      </Form.Group>
    <Button variant="primary" type="submit">
      Submit
    </Button>
  </Form>
  );
}

export default ContactForm;

ContactItem.js

import React from 'react';
import {Row, Col} from 'react-bootstrap';

const ContactItem = () =>{
  return(
    <Row>
      <Col lg = {1}>
        <img width = {50} src = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Unknown_person.jpg/542px-Unknown_person.jpg?20200423155822" alt = "" />
      </Col>
      <Col lg = {11}>
        <div></div>
        <div></div>
      </Col>
    </Row>
  );
}

export default ContactItem;

ContactList.js

import React from 'react';
import ContactItem from './ContactItem';
import SearchBox from './SearchBox';

const ContactList = () =>{
  return(
    <div>
      <SearchBox></SearchBox>
      <ContactItem></ContactItem>
    </div>
  );
}

export default ContactList;

ContactBox.js

import React from 'react';
import {Row, Col, Form, Button} from 'react-bootstrap';

const SearchBox = () =>{
  return(
    <Row>
      <Col lg = {10}>
        <Form.Control type = "text" placeholder = "์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”" />
      </Col>
      <Col lg = {2}>
        <Button>์ฐพ๊ธฐ</Button>
      </Col>
    </Row>
  );
}

export default SearchBox;

App.css

.title {
  text-align: center;
}

๐ŸŽˆ Redux ์—ฐ๊ฒฐ

sotre.js ํŒŒ์ผ ์ƒ์„ฑ

import {createStore} from 'redux';
import reducer from './reducer/reducer';

let store = createStore(reducer);
export default store;

reducer ํด๋” ์ƒ์„ฑ ํ›„ reducer.js ํŒŒ์ผ ์ƒ์„ฑ

let initialState = {
  contactList: [],
}

function reducer(state = initialState, action) {
  const {type, payload} = action;
  switch(type) {
    case 'ADD_CONTACT':
        return {
          ...state,
          contactList:[
            ...state.contactList,
            {
            name: action.payload.name,
            phoneNumber:action.payload.phoneNumber,
          },
        ],
      }
      default :
        return {...state};
  }
}

export default reducer;

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import store from './store';
import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store = {store}>
    <App />
  </Provider>
);

reportWebVitals();

ContactForm.js

import React, {useState} from 'react';
import {Form, Button} from 'react-bootstrap';
import { useDispatch } from 'react-redux';

const ContactForm = () => {
  const [name, setName] = useState('');
  const [phoneNumber, setPhoneNumber] = useState(0);
  const dispatch = useDispatch();

  const addContact = (event) =>{
    event.preventDefault();
    dispatch({
      type: 'ADD_CONTACT',
      payload: {name, phoneNumber},
    });
  }

  return(
    <Form onSubmit = {addContact}>
      <Form.Group className="mb-3" controlId="formName">
        <Form.Label>์ด๋ฆ„</Form.Label>
        <Form.Control type="text" placeholder="์ด๋ฆ„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”" 
        onChange = {(event) => setName(event.target.value)} />
    </Form.Group>

      <Form.Group className="mb-3" controlId="formBasicPassword">
        <Form.Label>์ „ํ™”๋ฒˆํ˜ธ</Form.Label>
        <Form.Control type="number" placeholder="์ „ํ™”๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”"
        onChange = {(event) => setPhoneNumber(event.target.value)} />
      </Form.Group>
      <Form.Group className="mb-3" controlId="formBasicCheckbox">
        <Form.Check type="checkbox" label="Check me out" />
      </Form.Group>
    <Button variant="primary" type="submit">
      Submit
    </Button>
  	</Form>
  );
}

export default ContactForm;

ContactList.js

import React from 'react';
import { useSelector } from 'react-redux';
import ContactItem from './ContactItem';
import SearchBox from './SearchBox';

const ContactList = () =>{
  const contactList = useSelector((state) => state.contactList);

  return(
    <div>
      <SearchBox/>
      {contactList.map((item) => (
      <ContactItem item = {item} />
      ))}
    </div>
  );
}

export default ContactList;

ContactItem.js

import React from 'react';
import {Row, Col} from 'react-bootstrap';

const ContactItem = ({item}) =>{
  return(
    <Row>
      <Col lg = {1}>
        <img width = {50} src = "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Unknown_person.jpg/542px-Unknown_person.jpg?20200423155822" alt = "" />
      </Col>
      <Col lg = {11}>
        <div>{item.name}</div>
        <div>{item.phoneNumber}</div>
      </Col>
    </Row>
  );
}

export default ContactItem;

๋ฆฌ์—‘ํŠธ ๊ด€๋ จ๋œ ๋ฌธ๋ฒ• ๊ณต๋ถ€๊ฐ€ ํ•„์š”ํ•œ๊ฒƒ ๊ฐ™๋‹ค.

profile
๋น„์ „๊ณต์ž์˜ ํ”„๋ก ํŠธ์•ค๋“œ ๋„์ „๊ธฐ

0๊ฐœ์˜ ๋Œ“๊ธ€