- JavaScript 상태관리 라이브러리
- Node.js 모듈
- 상태관리 툴 모듈 종류 중에 하나
▶ 자식 컴포넌트들 간의 다이렉트 데이터 전달은 불가능
▶ 자식 컴포넌트들 간의 데이터를 주고 받을 때는 상태를 관리하는 부모
컴포넌트를 통해서 주고 받는다
▶ 자식이 많아진다면 상태 관리가 매우 복잡해진다.
▶ 상태를 관리하는 상위 컴포넌트에서 계속 내려 받아야한다.
→ Props drilling 이슈
npm install redux react-redux
▶ 화면처럼 작동을 하기는 한다. 하핳
이번에 필요한 파일이 총 9개 정도 된다. 그래서 일단 미리 목록을 올려두려고 한다.
ContactForm.jsx
ContactItem.jsx
ContactList.jsx
SearchBox.jsx
reducer.js
App.css
App.js
store.js
index.js
import React, {useState} from "react";
import {Form, Button} from 'react-bootstrap';
import "bootstrap/dist/css/bootstrap.min.css";
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>Your Name</Form.Label>
<Form.Control
type="text"
placeholder="Enter Name"
onChange={(event) => setName(event.target.value)}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formContact">
<Form.Label>Your PhoneNumber</Form.Label>
<Form.Control
type="number"
placeholder="Enter PhoneNumber"
onChange={(event) => setPhoneNumber(event.target.value)}
/>
</Form.Group>
<Button variant="primary" type="submit">
Add
</Button>
</Form>
);
}
export default ContactForm;
import React from 'react';
import SearchBox from './SearchBox';
import "bootstrap/dist/css/bootstrap.min.css";
import ContactItem from './ContactItem';
import { useSelector } from 'react-redux';
const ContactList = () => {
const contactList = useSelector((state) => state.contactList);
return (
<div>
<SearchBox />
{contactList.map((item) => (
<ContactItem item={item} />
))}
</div>
);
};
export default ContactList;
import React from 'react';
import {Form, Button, Row, Col} from 'react-bootstrap';
import "bootstrap/dist/css/bootstrap.min.css";
import '../App.css';
const SearchBox = () => {
return (
<Row>
<Col lg={10}>
<Form.Label>Search Name</Form.Label>
<Form.Control type="text" placeholder="이름을 입력해주세요" />
</Col>
<Col lg={2}>
<Button id="search_btn">찾기</Button>
</Col>
</Row>
);
};
export default SearchBox;
import '../App.css';
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/925px-Unknown_person.jpg"
alt=""
id='img_unknown'
/>
</Col>
<Col lg={11} id='img_unknown'>
<div>{item.name}</div>
<div>{item.phoneNumber}</div>
</Col>
</Row>
);
};
export default ContactItem;
여기까지 컴포넌트를 완성하여
App.js
에 데이터를 모아주고index.js
에 연결하여 UI로 나타나게 해준다.
import './App.css';
import React from 'react';
import {Container, Row, Col} from 'react-bootstrap';
import ContactForm from './components/ContactForm';
import ContactList from './components/ContactList';
function App() {
return (
<div className="App">
<h1 className="title">연락처</h1>
<Container>
<Row>
<Col>
<ContactForm></ContactForm>
</Col>
<Col>
<ContactList></ContactList>
</Col>
</Row>
</Container>
</div>
);
}
export default App;
.title {
text-align: center;
/* border-top: 1px solid blue;
border-bottom: 1px solid blue; */
}
#search_btn {
margin-top: 32px;
margin-bottom: 32px;
}
#img_unknown {
margin-top: 10px;
margin-bottom: 10px;
}
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>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
위의 4개의 컴포넌트를
App.js
와index.js
순으로 거쳐서 UI를 생성
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;
import {createStore} from 'redux';
import reducer from './reducer/reducer';
let store = createStore(reducer);
export default store;
UI에서
Action
을 요청하면, 이를reducer
를 거쳐서,store
로 값이 저장된다. 그리고 이를 UI로 다시 보내주는 과정을 거치면, 아까처럼 입력하고 바로 화면에 값이 저장되는 결과를 낳게 한다.