[KDT]FCFE - 8주3일 React Practice
React
React Practice
HOC
: Higher Order Component ( 고차 컴포넌트 )
HOC = function(컴포넌트) { return 새로운 컴포넌트;}
- 컴포넌트를 받아 새로운 컴포넌트를 리턴하는 함수 이다.
withRouter(컴포넌트) -> router에 의해 호출되지 않아도 match, location, history 에 접근할 수 있도록 한다.
-
with 가 들어가는 HOC 가 많다.
-
cross-cutting concern ( 횡단 관심사 )
-
Original Component ( Use Composition ) : 그대로 사용하기
-
컴포넌트를 감싸놓아도 Unrelated Props 를 잘 넘겨주기
-
Easy Debugging : 디버깅이 쉽도록 새롭게 리턴한 컴포넌트에 displayName 표기하기.
주의점
-
render Method 에서 HOC 를 사용해서는 않된다.
-
인자로 들어간 component의 static Methods는 복사되지 않기 때문에 따로 복사하여 넣어줘야한다. ( 복사해서 넣어주는 라이브러리 : hoist-non-react-statics )
-
Reference는 바로 통과 되지 않는다. ( React.forwardRef 사용 )
Controlled Component & Uncontrolled Component
- 상태를 갖고 있는 엘리먼트 ( input, select, textarea ... )
Uncontrolled Component
- react 는 실제 돔에 접근하여 사용한것 보다는 엘리먼트가 갖고 있는 상태를 활용하도록 하는것이 좋다.
inputRef = React.createRef();
- Ref를 쓰기위해 준비하고
<input ref={this.inputRef}/>
- Ref를 사용할 태그에 지정해준 후
componentDidMount() {
console.log("componentDidMount", this.inputRef.current.value);
}
- mount 된 이후 참조되면 사용할 수 있다.
Hooks & Context
- Basick Hooks
( useState, useEffect, useContext )
React.useState()
const [count, setCount] = React.useState(0);
return (
<div>
<p>{count}</p>
<button onClick={setCount(count+1)}>클릭</button>
</div>
)
-
함수형 컴포넌트에서 state를 관리하기 위해서는 hook 을 사용해야한다.
-
useState 훅은 인자로 state 초기값을 전달하고 구조분해 할당으로 useState가 리턴하는 배열의 첫번째는 state의 변수 값을 할당하고 두번째 배열은 state를 변경할 수 있는 method를 할당한다.
const [state, setState] = React.useState({count:0,num:10});
return (
<div>
<p>{state.count}</p>
<button onClick={setState({count: state.count+1})}>클릭</button>
</div>
)
-
state를 객체로 관리하기위해서는 useState 인자로 객체를 넣고 state.key 로 관리할 수 있다.
-
setState를 사용할 때 인자에 객체의 프로퍼티를 변경하는 방식으로 state를 변경할 수 있다.
const [state, setState] = React.useState({count:0,num:10});
return (
<div>
<p>{state.count}</p>
<button onClick={setState((state)=>{ return { count: state.count + 1}})}>클릭</button>
</div>
)
- setState를 사용할 때 인자로 화살표 함수를 사용하여 state 인자를 넣고 객체를 리턴하는 방식을 사용함으로써 의존하지 않고 사용하는 방식을 알아두어야 한다.
useState Hook 을 사용하여 함수형에서 state를 관리하는 이유
-
컴포넌트 사이에서 상태와 관련된 로직을 재사용하기 어렵다.
-
복잡한 컴포넌트들은 이해하기 어렵다
-
class는 사람과 기계를 혼동시킨다.
-
this.state는 로직에서 reference를 공유하기 때문에 문제가 발생할 수 있다.
React.useEffect()
-
컴포넌트의 라이프사이클에 사용할 수 있다.
-
useEffect(첫번째, 두번째)
-
첫번째 인자에는 동작할 함수를 넣고 두번째 인자는 포커스할 state를 넣는다.
-
두번째 인자로 넣은 state 값이 변경되면서 rerendering일 일어나면 첫번째 인자에 넣은 함수가 동작한다.
-
두번째 인자에 아무것도 넣지 않으면 렌더가 일어날때마다 첫번째 인자로 넣은 함수가 동작한다.
-
두번째 인자에
[]
빈 배열을 넣으면 최초 렌더시에만 첫번째 인자로 넣은 함수가 동작한다. -
첫번째 인자의 함수에 리턴값으로 함수를 넣고 리턴된 함수는 첫번째 인자의 함수가 조건에 의해 동작한 후 rerender가 끝나면 즉, update 동작이 끝나면 리턴된 함수가 동작한다.
React.useEffect(()=>{
console.log("componentDidMount");
}, []);
React.useEffect(()=>{
console.log("componentDidMount & componentDidUpdate by count",count);
return () => {
// cleanup
console.log("cleanup by count", count);
};
}, [count]);
[https://rinae.dev/posts/a-complete-guide-to-useeffect-ko](useEffect 완벽 가이드)
Custom Hooks
import { useState, useEffect } from 'react';
exprot default function useWindowWidth(){
const [width, setWidth ] = useState(window.innerWidth);
// mount가 되자마자 dom 을 사용한다.
useEffect(()=>{
const resize = () => {
setWidth(window.innerWidth);
};
// resize event 를 걸어 놓는다.
window.addEventListener("resize", resize);
return () => {
// 걸어놓은 event를 제거해야한다.
window.removeEventListener("resize", resize);
};
}, []);
return width;
}
HOC
-
component를 인자로 넣고 component를 리턴한다.
-
component가 랜더된 후나 전에 component에 props를 넣어주거나 변경할 수 있다.
-
props 넣어주는 HOC 만들기
import React from "react";
export default function withHasMounted(Component) {
class NewComponent extends React.Component {
state = {
hasMounted: false,
};
render(){
const { hasMounted } = this.state;
// 리턴값으로 props를 넣은 컴포넌트를 돌려준다.
// state가 변경되면 리렌더되면서 변경된 props를 넣은 component가 리턴된다.
return <Component {...this.props} hasMounted={ hasMounted }/>
}
// Mount 후 hasMounted 값 변경
componentDidMount(){
this.setState({ hasMounted: true});
}
}
NewComponent.displayName = `withHasMounted(${Component.name})`;
return NewComponent;
}
import withHasMounted from "./hocs/withHasMounted";
function App({ hasMounted }){
console.log(hasMounted);
return (
<div className="App">
...
</div>
);
}
export default withHasMounted(App);
// false *초기값
// true *mount 후 변경값
// HOC 가 적용되어 두번 출력됨.
Additional Hooks
- useReducer
import { useReducer } from "react";
const reducer = (state, action) => {
if (action.type === "PLUS") {
return { count2: state.count2 + 1 };
}
return state;
};
const MyButton = () => {
const [state, dispatch] = useReducer(reducer, { count2: 0 });
console.log("rendering");
function onClick() {
dispatch({ type: "PLUS" });
}
return (
<div>
<button onClick={onClick}>{state.count2}</button>
</div>
);
};
export default MyButton;
- useMemo
useEffect 와 비슷하게 의존하는 두번째 인자가 변경될때 실행 되도록 한다.
- useCallback
첫번째 인자로 넣은 함수를 변경하는 시점을 의존적으로 사용한다.
즉, 두번째 인자로 넣은 값이 변경될때 첫번째 인자로 넣은 함수도 변경된다.
import { useState, useMemo } from "react";
function sum(persons) {
console.log('sum...');
return persons.map((person)=>person.age).reduce((l,r)=>l+r);
}
export default function Example7(){
const [value, setValue] = useState("");
const [persons] = useState([
{ name: "Mark", age: 39 },
{ name: "Mark", age: 39 },
]);
const count = useMemo(()=>{
return sum(persons);
}, [persons]);
const click = useCallback(()=>{
console.log(value);
})
return (
<div>
<input value={value} onChange={change} />
<p>{count}</p>
<button onClick={click}>click</button>
</div>
);
function change(e){
setValue(e.target.value)
}
}
- useRef
render 사이에 유지를 해주도록 한다.
함수형 컴포넌트는 전부 새로 랜더되므로 랜더시 유지해주는 훅이 존재한다.
import { createRef, useRef, useState } from 'react';
export default function Example8 () {
const [value, setValue] = usestate("");
// 랜더가 일어 날때 마다 새롭게 참조를 생성해서 참조한다.
const input1Ref = createRef();
// render 될때마다 실행되는것이 아니라 한번 참조하면 그대로!
const input2Ref = useRef();
console.log(input1Ref.current, input2Ref.current);
return (
<div>
<input value={value} onChange= {change} />
<input ref={input1Ref} />
<input ref={input2Ref} />
</div>
);
function change(e){
setValue(e.target.value);
}
}
React Router Hooks
useHistory
- 함수를 실행하는 것으로 현재 component의 history를 받을 수 있다.
const history = useHistory();
history.push("/");
useParams
const params = useParams();
const id = params.id;
Context API
import React from "react";
const PersonContext = React.createContext();
export default PersonContext;
- index.js
const persons = [
{id: 0, name: "Mark", age: 29},
{id: 1, name: "Hanna", age: 34}
];
ReactDOM.render(
<Personcontext.Provider value = {persons}>
<App />
</Personcontext.Provider>
)
- Example1.jsx
:Consumer 사용.
import Personcontext from "../contexts/PersonContext"
export default function Example1() {
return(
<Personcontext.Consumer>
{(persons)=>{
return (
<ul>
{
persons.map((person)=>(
<li>{person.name}</li>
))}
</ul>
)}}
</Personcontext.Consumer>
);
}
- Example2.jsx
: useContext 훅 사용 (가장 많이 사용) -> 함수의 리턴값이 value
import { useContext } from "react";
import Personcontext from "../contexts/PersonContext"
export default function Example1() {
const persons = useContext(PersonContext);
return(
<ul>
{persons.map((person)=>(
<li>{person.name}</li>
))}
</ul>
);
}
Author And Source
이 문제에 관하여([KDT]FCFE - 8주3일 React Practice), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@leedocs/KDTFCFE-8주3일-React-Practice저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)