Context API
context를 이용하면 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있습니다.
- Reactjs.org
context 없이 props를 전달하여 화면 표시
import React, {createContext, useContext} from 'react'; function Child({text}){ return <div>Hello? {text}</div> } function Parent({text}){ return <Child text = {text}/> } function GrandParent({text}){ return <Parent text = {text} /> } function ContextSample(){ return <GrandParent text = "GOOD"/> } export default ContextSample;
context를 이용하여 자식 컴포넌트에서 바로 데이터를 사용
import React, {createContext, useContext, useState} from 'react'; const MyContext = createContext('defaultValue'); function Child(){ const text = useContext(MyContext); return <div>Hello? {text}</div> } function Parent(){ return <Child/> } function GrandParent(){ return <Parent/> } function ContextSample(){ const [value, setValue] = useState(true); return ( <MyContext.Provider value = {value ? 'GOOD' : 'BAD'}> <GrandParent /> <button onClick = {() => setValue(!value)}>CLICK ME</button> </MyContext.Provider> ); } export default ContextSample;
- context를 이용하면, 트리 단계마다 명시적으로 props를 넘겨주지 않아도 많은 컴포넌트가 이러한 값을 공유할 수 있다.
immer library
불변성을 조금 더 수월하게 지킬 수 있도록 도와준다.
const object = {
a: 1,
b: 2
};
const nextObject = {
//1
...object,
b: 3
};
object.b = 3;//2
- 해당 객체를 스프레드를 이용하여 복사하고 값을 덮어씌우는 것이 불변성을 지킨다.
- 직접 객체에 접근하여 대입하는 것은 불변성을 깨는 행위이다.
배열의 경우 새로운 요소를 생성해 줄 때 위와 같이 복사하고 추가하는 내용들의 코드는 점차 알아보기 힘들어진다.
immer 라이브러리는 불변성을 깨더라도 대신 불변성을 유지해준다.yarn add immer
를 통해 라이브러리를 설치한다.
reducer 정의한 함수를 통해 비교해보자.
- 기존
function reducer(state, action){ switch(action.type){ return{ inputs: initialState.inputs, users: state.users.concat(action.user) } case 'TOGGLE_USER': return{ ...state, users: state.users.map( user => user.id === action.id ? {...user, active: !user.active} : user ) } case 'REMOVE_USER': return{ ...state, users: state.users.filter( user => user.id !== action.id ) } default: throw new Error('Unhandled Action'); } }
- immer
function reducer(state, action){ switch(action.type){ case 'CREATE_USER': return produce(state, draft => { draft.users.push(action.user); }); case 'TOGGLE_USER': return produce(state, draft=>{ const user = draft.users.find(user => user.id == action.id); user.active = !user.active; }); case 'REMOVE_USER': return produce(state, draft =>{ const index = draft.users.findIndex(user => user.id == action.id); draft.users.splice(index,1); }); default: throw new Error('Unhandled Action'); } }
- CREATE_USER나 REMOVE_USER같은 경우는 오히려 복잡해졌으나, TOGGLE_USER의 경우 더 보기 편해졌다.
- TOGGLE_USER와 같이 안의 요소를 수정하거나 조금 더 큰 객체일 경우 쓰는 것을 추천
- 남발하는것은 좋지 않다.
class 형 컴포넌트
요즘은 잘 쓰지 않으며, 옛날 코드들을 유지보수 할 경우에 쓰는 것을 추천함
또는 함수형 컴포넌트와 Hooks로 작업하지 못하는 경우 사용하는 것을 추천함
사용법
import React, {Component} from "react"; class Hello extends Component{ static defaultProps = { name: '이름없음' } render(){ const {color, isSpecial, name} = this.props return ( <div style = {color}> {isSpecial && <b>*</b>} 안녕하세요 {name} </div> ) } } export default Hello
class 함수 사용
class Counter extends Component { constructor(props){ super(props); } handleIncrease(){ console.log("handleIncrease"); } handleDecrease(){ console.log("handleDecrease"); } render(){ return( <div> <h1>0</h1> <button onClick = {this.handleIncrease}>+1</button> <button onClick = {this.handleDecrease}>-1</button> </div> ) } }
- 단, onClick으로 함수를 보내면 this는 사용이 불가하다.
- onClick으로 함수를 보낼 때 컴포넌트 인스턴스와 메서드의 관계가 끊기기 때문이다.
- 이를 방지하기 위해 생성자를 만들어주어 bind를 해준다.
constructor(props){ super(props); this.handleIncrease = this.handleIncrease.bind(props); this.handleDecrease = this.handleDecrease.bind(props); }
- 또는 화살표 함수 문법을 이용한다.
handleIncrease = () => { console.log("handleIncrease"); } handleDecrease = () => { console.log("handleDecrease"); }
- 단, onClick으로 함수를 보내면 this는 사용이 불가하다.
상태유지
Counter.js
class Counter extends Component { constructor(props){ super(props); this.state = { counter: 0, fixed: 1, updateMe: { toggleMe: false, dontChangeMe: 1, } }; } handleIncrease = () => { this.setState({ counter: this.state.counter+1 }); } handleDecrease = () => { this.setState({ counter: this.state.counter-1 }); } render(){ return( <div> <h1>{this.state.counter}</h1> <button onClick = {this.handleIncrease}>+1</button> <button onClick = {this.handleDecrease}>-1</button> <h6>{this.state.fixed}</h6> </div> ) } }
- 기본적으로 state를 수정할 때 바로 수정이 가능하다.
- 다만, stete가 가지고 있는 객체를 수정할 때 기존 함수 state 수정하듯 객체를 복사해주고 수정해야한다.
updateMe:{ ...this.state.updateMe, toggleMe: !this.state.updateMe.toggleMe, }
- 불변성을 지키기 위함
setState 함수형 업데이트 가능
handleIncrease = () => { this.setState(state => ({ counter: state.counter+1 })); } handleDecrease = () => { this.setState(state => ({ counter: state.counter-1 })); }
LifeCycle 메서드
(생명주기 메서드)
브라우저 상에 컴포넌트가 나타나고 업데이트 되고 사라지게 될 때 호출되는 메서드이다.
컴포넌트가 에러가 발생했을 때 호출되는 메서드도 이 메서드의 일부이기도 하다.
이는 class형 컴포넌트에서만 사용이 가능하다.
(useEffect와 유사함, 작동방식이 다르며, 커버하지 않는 기능도 존재)
각종도구
- Prettier: 자동으로 코드 스타일을 관리해주는 도구
- ESlint: 코드를 분석해 문법적인 오류나 안티 패턴을 찾아주고 일관된 코드 스타일로 작성하도록 도와준다.
- Snippet: 단축키
'WebStudy' 카테고리의 다른 글
React Router (0) | 2021.02.19 |
---|---|
React API (0) | 2021.02.18 |
React 기본 2 (0) | 2021.02.13 |
React 기본 1 (0) | 2021.02.12 |
Web Server 및 WAS (0) | 2021.02.06 |
최근댓글