[TIL] 엘리스 SW 엔지니어 트랙 Day 059
글 작성자: 망고좋아
반응형
📖 오늘 배운 내용 - 2022.01.13
- react-redux
- 테스트
📝 리덕스 없이 리액트 구현 :: props drilling
import {useState} from 'react';
import './App.css';
function App() {
const [value, setValue] = useState(0);
return (
<div>
<h1>Root</h1>
{value}
<div id="container">
<Left1 number={value}></Left1>
<Right1 onIncrease={() => {
setValue(value+1)
}}></Right1>
</div>
</div>
);
}
function Left1(props){
return <div>
<h2>Left1 : {props.number}</h2>
<Left2 number={props.number}></Left2>
</div>
}
function Left2(props){
return <div>
<h3>Left2 : {props.number}</h3>
<Left3 number={props.number}></Left3>
</div>
}
function Left3(props){
return <div>
<h4>Left3 : {props.number}</h4>
<Left4 number={props.number}></Left4>
</div>
}
function Left4(props){
return <div>
<h5>Left4 : {props.number}</h5>
</div>
}
function Right1(props){
return <div>
<h2>Right1</h2>
<Right2 onIncrease={() => {
props.onIncrease();
}}></Right2>
</div>
}
function Right2(props){
return <div>
<h3>Right2</h3>
<Right3 onIncrease={() => {
props.onIncrease();
}}></Right3>
</div>
}
function Right3(props){
return <div>
<h4>Right3</h4>
<Right4 onIncrease={() => {
props.onIncrease();
}}></Right4>
</div>
}
function Right4(props){
return <div>
<h5>Right4</h5>
<input type="button" value="+" onClick={() => {
props.onIncrease();
}}></input>
</div>
}
export default App;
📝 리덕스로 구현
npm install redux react-redux
- Provider는 Provider 하위에서 컴포넌트를 사용할 거다 라는 말이다.
- useSelector는 함수를 인자로 받는다.
🛠 index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {BrowserRouter} from 'react-router-dom';
import {createStore} from 'redux';
import {Provider, useDispatch, useSelector} from 'react-redux';
function reducer(oldState, action){
if(oldState === undefined){
return {
mode:'WELCOME',
topics:[
{id:1, title:'html', body:'html is ..'},
{id:2, title:'css', body:'css is ..'}
],
nextId:3
}
}
const newState = {...oldState}
if(action.type === 'CHANGE_MODE'){
newState.mode = action.mode;
} else if(action.type === 'CHANGE_ID'){
newState.id = action.id;
} else if(action.type === 'CREATE'){
const newTopics = [...newState.topics];
newTopics.push({
id:newState.nextId,
title:action.title,
body:action.body
});
newState.topics = newTopics;
} else if(action.type === 'UPDATE'){
const newTopics = [...newState.topics];
for(let i=0; i<newTopics.length; i++){
let t = newTopics[i];
if(t.id === action.id){
t.title = action.title;
t.body = action.body;
}
}
newState.topics = newTopics;
} else if(action.type === 'DELETE'){
let newTopics = [];
for(let i=0; i<newState.topics.length; i++){
let t = newState.topics[i];
if(t.id !== action.id){
newTopics.push(t);
}
}
newState.topics = newTopics;
} else if(action.type === 'INCREASE_NEXT_ID'){
newState.nextId++;
}
return newState;
}
const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<Provider store={store}>
<App />
</Provider>
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
// 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();
🛠 App.js
import './App.css';
import {useState} from 'react';
import {Link,Routes,Route,useParams,useNavigate} from 'react-router-dom';
import {Provider, useDispatch, useSelector} from 'react-redux';
function Header(props){
return <header>
<h1><Link to="/">{props.title}</Link></h1>
</header>
}
function Nav(props){
let lis = []
for(let i=0; i<props.data.length; i=i+1){
let d = props.data[i];
lis.push(<li key={d.id}><Link to={'/read/'+d.id}>{d.title}</Link></li>)
}
return <nav>
<ol>
{lis}
</ol>
</nav>
}
function Article({title, body}){
console.log('Article');
return <article>
<h2>{title}</h2>
{body}
</article>
}
function Create(props){
function submitHandler(evt){
evt.preventDefault();
let title = evt.target.title.value;
let body = evt.target.body.value;
props.onSubmit(title, body)
console.log(title);
}
return <article>
<h2>Create</h2>
<form onSubmit={submitHandler}>
<p><input type="text" name="title" placeholder="title" /></p>
<p><textarea name="body" placeholder="body"></textarea></p>
<p><input type="submit" value="create" /></p>
</form>
</article>
}
function Update(props){
const params = useParams();
const id = Number(params.id);
const topics = props.topics;
let _title = null;
let _body = null;
for(let i=0; i<topics.length; i++){
if(topics[i].id === id){
_title = topics[i].title;
_body = topics[i].body;
}
}
const [title, setTitle] = useState(_title);
const [body, setBody] = useState(_body);
function submitHandler(evt){
evt.preventDefault();
let title = evt.target.title.value;
let body = evt.target.body.value;
props.onSubmit(id, title, body)
console.log(title);
}
return <article>
<h2>Update</h2>
<form onSubmit={submitHandler}>
<p><input type="text" name="title" placeholder="title" value={title} onChange={evt=>setTitle(evt.target.value)} /></p>
<p><textarea name="body" placeholder="body" value={body} onChange={evt=>setBody(evt.target.value)}></textarea></p>
<p><input type="submit" value="update" /></p>
</form>
</article>
}
function App() {
console.log('App');
const [mode, setMode] = useState('WELCOME');
const [id, setId] = useState(null);
const navigate = useNavigate();
console.log('id', id);
// const [nextId, setNextId] = useState(4);
const nextId = useSelector(state=>state.nextId);
// const [topics, setTopics] = useState([
// {id:1, title:'html', body:'html is ...'},
// {id:2, title:'css', body:'css is ...'},
// {id:3, title:'js', body:'js is ...'}
// ]);
const topics = useSelector(state=>state.topics);
const dispatch = useDispatch();
function changeModeHandler(id){
// let newTopics = [];
// for(let i=0; i<topics.length; i++){
// if(topics[i].id !== id){
// newTopics.push(topics[i]);
// }
// }
// setTopics(newTopics); todo
dispatch({type:'DELETE', id:id});
navigate('/');
return;
}
return (
<>
<Header title="WEB" onChangeMode={changeModeHandler}/>
<Nav data={topics} onChangeMode={changeModeHandler}/>
<Routes>
<Route path="/" element={<Article title="Welcome" body="Hello, React!"/>}></Route>
<Route path="/read/:id" element={<Read topics={topics}></Read>}></Route>
<Route path="/create" element={
<Create onSubmit={(_title, _body)=>{
// let newTopic = {id:nextId, title:_title, body:_body}
// let newTopics = [...topics];
// newTopics.push(newTopic);
// setTopics(newTopics); todo
// setMode('READ');
// setId(nextId);
dispatch({type:'CREATE', title:_title, body:_body});
navigate('/read/'+nextId);
// setNextId(nextId+1);
dispatch({type:'INCREASE_NEXT_ID'});
}}></Create>
}></Route>
<Route path="/update/:id" element={<Update topics={topics} onSubmit={(id, title, body)=>{
// let newTopics = [...topics];
// for(let i=0; i<newTopics.length; i++){
// if(newTopics[i].id === id){
// newTopics[i].title = title;
// newTopics[i].body = body;
// }
// }
// setTopics(newTopics); todo
dispatch({type:'UPDATE', id:id, title:title, body:body});
navigate('/read/'+id);
}}></Update>}></Route>
</Routes>
<Routes>
<Route path="/" element={<Control />}></Route>
<Route path="/read/:id" element={<Control onDelete={changeModeHandler} />}></Route>
</Routes>
</>
);
}
function Read(props){
const params = useParams();
const id = Number(params.id);
const topics = props.topics;
let title = null;
let body = null;
for(let i=0; i<topics.length; i++){
if(topics[i].id === id){
title = topics[i].title;
body = topics[i].body;
}
}
return <Article title={title} body={body}/>
}
function Control(props){
const params = useParams();
const selectedId = Number(params.id);
let contextUI = null;
if(selectedId>0){
contextUI = <>
<li>
<Link to={'/update/'+selectedId}>update</Link>
</li>
<li>
<form onSubmit={evt=>{
evt.preventDefault();
props.onDelete(selectedId);
}}>
<input type="submit" value="delete" />
</form>
</li>
</>
}
return <ul>
<li><Link to="/create">create</Link></li>
{contextUI}
</ul>
}
export default App;
📝 테스트
- Test Driven Development : TDD
- 요즘은 테스트 코드를 작성하고 코드를 작성한다.
- 생산성에 저하가 올 수 있지만 견고하고 탄탄한 코드를 작성할 수 있다.
- Unit test
- 하나의 모듈을 기준으로 독립적으로 동작하는 가장 작은 단위의 테스트 → React Component
- 어떤 컴포넌트 기능이 하나 있다면 그 기능에 대응하는 테스트 하나를 만들게 된다.
- Integration Test
- 전체 테스트
- 호환성을 위해서 하는 테스트
💡 오늘 깨달은 것
- 실시간 수업, 온라인 수업, 문제 등 버전이 다르다 보니 너무 헷갈린다. 학습은 함수형으로 배우다가 문제는 클래스형으로 나오고...
- 테스팅은 재밌으면서도 어려워 보인다.
📌 참고
반응형
'프로그래밍 > Today I Learned' 카테고리의 다른 글
[TIL] 엘리스 SW 엔지니어 트랙 Day 061 (0) | 2022.01.17 |
---|---|
[TIL] 엘리스 SW 엔지니어 트랙 Day 060 (0) | 2022.01.17 |
[TIL] 엘리스 SW 엔지니어 트랙 Day 058 (0) | 2022.01.16 |
[TIL] 엘리스 SW 엔지니어 트랙 Day 057 (0) | 2022.01.16 |
[TIL] 엘리스 SW 엔지니어 트랙 Day 056 (0) | 2022.01.13 |
댓글
이 글 공유하기
다른 글
-
[TIL] 엘리스 SW 엔지니어 트랙 Day 061
[TIL] 엘리스 SW 엔지니어 트랙 Day 061
2022.01.17 -
[TIL] 엘리스 SW 엔지니어 트랙 Day 060
[TIL] 엘리스 SW 엔지니어 트랙 Day 060
2022.01.17 -
[TIL] 엘리스 SW 엔지니어 트랙 Day 058
[TIL] 엘리스 SW 엔지니어 트랙 Day 058
2022.01.16 -
[TIL] 엘리스 SW 엔지니어 트랙 Day 057
[TIL] 엘리스 SW 엔지니어 트랙 Day 057
2022.01.16