useState()는 함수형 컴포넌트 내부에서 state 값을 관리(변경 등)을 하기 위해 사용하는 Hook입니다.
const [ state,setState ] = useState(기본값);
구조 분해 할당을 통해 useState를 이용합니다.
보통 첫번째 배열 요소에 state 값을 넣고, 두번째 요소로 state 요소를 설정하는 함수를 넣어줍니다.
state설정 함수의 인자로 전달받은 값이 변경할 state값이 됩니다.
const onChange=()=>{
setState(변경값)
}
이 글에 정리해 놨으나
useEffect(() => {
~~~ 실행할 함수들~~~
예를들어 여기서 setTimeout을 사용햇다면,
return () => { // componentWillUnmount
//이곳에서 클리어 해줘야 한다.
});
};
}, []); //빈 배열이면 ComponenetDidMount
// 배열에 요소가 있으면, componentDidMount,componentDidUpdate
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
본질적으로 useRef는 .current 프로퍼티에 변경 가능한 값을 담고 있는 “상자”와 같습니다.
위와 같이 Dom에 접근하여 focus를 주는 방법도 있지만,
어떤 가변값을 유지하는데에 편리합니다.
useRef는 매번 렌더링을 할 때 동일한 ref 객체를 제공한다는 것입니다.
useRef는 내용이 변경될 때 그것을 알려주지는 않는다는 것을 유념하세요.
current 프로퍼티를 변형하는 것이 리렌더링을 발생시키지는 않습니다.
일반적인 React 애플리케이션에서 데이터는 위에서 아래로 (즉, 부모로부터 자식에게) props를 통해 전달되지만, 애플리케이션 안의 여러 컴포넌트들에 전해줘야 하는 props의 경우 (예를 들면 선호 로케일, UI 테마) 이 과정이 번거롭고, 에러를 유발 할 수 있습니다.
context를 이용하면, 트리 단계마다 명시적으로 props를 넘겨주지 않아도
많은 컴포넌트가 이러한 값을 공유하도록 할 수 있습니다.
ontext는 React 컴포넌트 트리 안에서 전역적(global)이라고 볼 수 있는 데이터를 공유할 수 있도록 고안된 방법입니다. 그러한 데이터로는 현재 로그인한 유저, 테마, 선호하는 언어 등이 있습니다
const value = useContext(MyContext);
context의 현재 값은 트리 안에서 이 Hook을 호출하는 컴포넌트에 가장 가까이에 있는 <MyContext.Provider>
의 value prop에 의해 결정됩니다.
컴포넌트에서 가장 가까운 <MyContext.Provider>가 갱신되면 이 Hook은 그 MyContext provider에게 전달된 가장 최신의 context value를 사용하여 렌더러를 트리거 합니다.
즉, 상위컴포넌트에서 React.Memo를 사용해도, useContext를 사용 하고 있는
컴포넌트 자체에서부터 재 랜더링 됩니다.
useContext를 호출한 컴포넌트는 context 값이 변경되면 항상 리렌더링 될 것입니다.
컴포넌트를 리렌더링 하는 것에 비용이 많이 든다면, 메모이제이션을 사용하여 최적화할 수 있습니다.
function Button() {
let appContextValue = useContext(AppContext);
let theme = appContextValue.theme; // Your "selector"
return useMemo(() => {
// The rest of your rendering logic
return <ExpensiveTree className={theme} />;
}, [theme])
}
- - - - - -
function Button() {
let appContextValue = useContext(AppContext);
let theme = appContextValue.theme; // Your "selector"
return <ThemedButton theme={theme} />
}
const ThemedButton = memo(({ theme }) => {
// The rest of your rendering logic
return <ExpensiveTree className={theme} />;
});
const themes = {
light: {
foreground: "#000000",
background: "#eeeeee"
},
dark: {
foreground: "#ffffff",
background: "#222222"
}
};
const ThemeContext = React.createContext(themes.light);
function App() {
return (
<ThemeContext.Provider value={themes.dark}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
);
}
다수의 하윗값을 포함하는 복잡한 정적 로직을 만드는 경우나 다음 state가 이전 state에 의존적인 경우에 보통 useState보다 useReducer를 선호합니다.
또한 useReducer는 자세한 업데이트를 트리거 하는 컴포넌트의 성능을 최적화할 수 있게 하는데,
이것은 콜백 대신 dispatch를 전달 할 수 있기 때문입니다.
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
메모이제이션된 콜백을 반환합니다.
deps의 state가 변경 되기전까지 안에 함수를 저장해둡니다.
useCallback(fn, deps)은 useMemo(() => fn, deps)와 같습니다.