react hooks 구현 원리
react hooks 구현
Hooks가 어떤 문제를 해결했는지.
React
의 디자인 철학에서 간단하게 말하면 다음과 같은 공식으로 나타낼 수 있다.UI = f(data)
등호의 왼쪽에 UI가 대표하는 최종적으로 그려진 인터페이스;등호의 오른쪽은 함수, 즉 우리가 쓴 React와 관련된 코드이다.데이터는 데이터입니다. React에서 데이터는state나props일 수 있습니다.UI는 데이터를 매개 변수로 f에 전달하여 연산한 결과입니다.이 공식의 의미는 인터페이스를 렌더링하려면 DOM 요소를 직접 조종하지 말고 데이터를 수정하고 데이터가React를 구동해서 인터페이스를 수정하는 것이다.우리 개발자가 해야 할 일은 합리적인 데이터 모델을 설계하여 우리의 코드가 데이터에 근거하여 인터페이스를 어떻게 그려야 하는지를 설명하고 브라우저의DOM 트리 구조를 어떻게 조작해야 하는지를 고민하지 않도록 하는 것이다.전체적인 설계 원칙:
UI = f(data)
class SomeCompoent extends Component {
componetDidMount() {
const node = this.refs['myRef'];
node.addEventListener('mouseDown', handlerMouseDown);
node.addEventListener('mouseUp', handlerMouseUp)
}
...
componetWillunmount() {
const node = this.refs['myRef'];
node.removeEventListener('mouseDown', handlerMouseDown)
node.removeEventListener('mouseUp', handlerMouseUp)
}
}
후크스의 등장은 위의 문제들이 모두 쉽게 풀린다고 할 수 있다.'리액트 훅스로 바퀴 만들기'도입
Hooks API 유형
공식 성명에 따르면 hooks는 완전히 뒤로 호환되며,class componet은 제거되지 않으며, 개발자로서 최신 API로 천천히 이동할 수 있다.
Hooks는 주로 세 가지로 나뉜다.
다음은 Hooks에 대해 알아보겠습니다.
State hooks를 먼저 접했습니다.
use State는 우리가 처음으로React Hooks를 접한 것이다. 그 주요 역할은Function Component가state를 사용할 수 있도록 하고 매개 변수를 받아들여state의 초기 값으로 삼아 현재state와dispatch를 되돌려주는 것이다.
import { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} timesp>
<button onClick={() => setCount(count + 1)}>
Click me
button>
div>
);
}
그 중에서useState는 여러 번 성명할 수 있다.
function FunctionalComponent () {
const [state1, setState1] = useState(1)
const [state2, setState2] = useState(2)
const [state3, setState3] = useState(3)
return <div>{state1}{...}div>
}
이에 대응하는 hooks와useReducer가 있습니다. 상태가 다른 종류의 업데이트 처리에 대응하는 경우useReducer를 사용할 수 있습니다.
그다음에 Effect hooks를 접했어요.
useEffect의 사용은 Function Componet 구성 요소가life-cycles 성명 주기 함수를 갖추도록 하는 것이다.예를 들어componetDidMount,componetDidUpdate,shouldCompoentUpdate와componetWiillunmount는 모두 이 함수에 집중되어 집행되고useEffect라고 한다.이 함수는 Redux의subscribe와 약간 유사하며,props,state가render를 터치할 때마다 실행됩니다.(구성 요소의 첫 번째render와 매번 업데이트 후에 터치합니다.)왜 useEffect라고 하죠?공식적인 설명: 왜냐하면 우리는 보통 생명 주기 내에 많은 조작을 하면side-effect(부작용)의 조작이 발생하기 때문이다. 예를 들어DOM,fetch 데이터 업데이트 등이다.
useEffect는 다음을 사용합니다.
import React, { useState, useEffect } from 'react';
function useMousemove() {
const [client, setClient] = useState({x: 0, y: 0});
useEffect(() => {
const handlerMouseCallback = (e) => {
setClient({
x: e.clientX,
y: e.clientY
})
};
// render , didMount
document.addEventListener('mousemove', handlerMouseCallback, false);
return () => {
//
document.removeEventListener('mousemove', handlerMouseCallback, false);
}
})
return client;
}
그 중에서useEffect는 구성 요소가 처음render 이후didMount에 호출되었을 뿐이고, 구성 요소가 마운트 해제되었을 때 unmount 이후에 호출되었을 뿐입니다. DOM 업데이트 후에 동기화할 필요가 있으면useLayoutEffect를 사용할 수 있습니다.
마지막으로 접한 건 커스텀 훅스예요.
정부에서 제공하는useXXXAPI를 자신의 업무 장면과 결합하여 사용자 정의 개발에 필요한custom hooks를 사용하여 업무 개발 데이터를 추출하고 수요에 따라 도입할 수 있다.업무 데이터와 보기 데이터의 충분한 결합을 실현하다.
Hooks 구현 방법
위의 기초를 바탕으로 hooks의 사용에 대해 기본적인 이해를 얻었을 것이다. 다음은 hooks 원본 코드와 결합하여 hooks가 무상태 구성 요소를 어떻게 보존할 수 있는지의 원리를 박리한다.
Hooks 소스는 Reactreact-reconclier**의 ReactFiberHooks입니다.js, 코드는 600줄이 있어서 이해하기에도 편리합니다. 원본 주소: 여기
Hooks의 기본 유형:
type Hooks = {
memoizedState: any, // Fiber
baseState: any, // initialState, dispatch newState
baseUpdate: Update<any> | null,// Update , , update, react ,
queue: UpdateQueue<any> | null,// UpdateQueue
next: Hook | null, // link hooks, next hooks
}
type Effect = {
tag: HookEffectTag, // effectTag hook life-cycles
create: () => mixed, // callback
destroy: (() => mixed) | null, // callback
deps: Array<mixed> | null,
next: Effect, //
};
React Hooks 전역에는 Hooks API를 호출할 때마다 함수
workInProgressHook
를 먼저 호출하는 createWorkInProgressHooks
변수가 유지됩니다.function createWorkInProgressHook() {
if (workInProgressHook === null) {
// This is the first hook in the list
if (firstWorkInProgressHook === null) {
currentHook = firstCurrentHook;
if (currentHook === null) {
// This is a newly mounted hook
workInProgressHook = createHook();
} else {
// Clone the current hook.
workInProgressHook = cloneHook(currentHook);
}
firstWorkInProgressHook = workInProgressHook;
} else {
// There's already a work-in-progress. Reuse it.
currentHook = firstCurrentHook;
workInProgressHook = firstWorkInProgressHook;
}
} else {
if (workInProgressHook.next === null) {
let hook;
if (currentHook === null) {
// This is a newly mounted hook
hook = createHook();
} else {
currentHook = currentHook.next;
if (currentHook === null) {
// This is a newly mounted hook
hook = createHook();
} else {
// Clone the current hook.
hook = cloneHook(currentHook);
}
}
// Append to the end of the list
workInProgressHook = workInProgressHook.next = hook;
} else {
// There's already a work-in-progress. Reuse it.
workInProgressHook = workInProgressHook.next;
currentHook = currentHook !== null ? currentHook.next : null;
}
}
return workInProgressHook;
}
다음 hooks 코드를 실행해야 한다고 가정하십시오.
function FunctionComponet() {
const [ state0, setState0 ] = useState(0);
const [ state1, setState1 ] = useState(1);
useEffect(() => {
document.addEventListener('mousemove', handlerMouseMove, false);
...
...
...
return () => {
...
...
...
document.removeEventListener('mousemove', handlerMouseMove, false);
}
})
const [ satte3, setState3 ] = useState(3);
return [state0, state1, state3];
}
React Hooks의 간단한 원리를 이해하면 Hooks의 직렬은 하나의 그룹이 아니지만 하나의 체인식 데이터 구조로 루트 노드workInProgressHook에서 아래로next를 통해 직렬로 연결된다.이것이 바로 Hooks는 끼워서 사용할 수 없고 조건 판단에서 사용할 수 없고 순환에서 사용할 수 없는 이유다.그렇지 않으면 체인 구조를 파괴할 것이다.
질문 1:useState dispatch 함수를 사용하는 Function Component와 바인딩하는 방법
코드부터 살펴보겠습니다.
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
const useWindowSize = () => {
let [size, setSize] = useState([window.innerWidth, window.innerHeight])
useEffect(() => {
let handleWindowResize = event => {
setSize([window.innerWidth, window.innerHeight])
}
window.addEventListener('resize', handleWindowResize)
return () => window.removeEventListener('resize', handleWindowResize)
}, [])
return size
}
const App = () => {
const [ innerWidth, innerHeight ] = useWindowSize();
return (
<ul>
<li>innerWidth: {innerWidth}li>
<li>innerHeight: {innerHeight}li>
ul>
)
}
ReactDOM.render(<App/>, document.getElementById('root'))
State의 역할은 Function Component가 State의 능력을 갖추도록 하는 것이다. 그러나 개발자에게 Function Component에 hooks 함수를 도입하면 디스패치가 현재 구성 요소에 정확하게 작용할 수 있다. 무심코 이런 의문이 생길 수 있다. 이 의문을 가지고 원본 코드를 읽어보자.
function useState(initialState){
return useReducer(
basicStateReducer,
// useReducer has a special case to support lazy useState initializers
(initialState: any),
);
}
function useReducer(reducer, initialState, initialAction) {
// rendering Fiber
let fiber = (currentlyRenderingFiber = resolveCurrentlyRenderingFiber());
workInProgressHook = createWorkInProgressHook();
//
...
...
...
// dispathAction Fiber, dispatchAction
const dispatch = dispatchAction.bind(null, currentlyRenderingFiber,queue,)
return [workInProgressHook.memoizedState, dispatch];
}
function dispatchAction(fiber, queue, action) {
const alternate = fiber.alternate;
const update: Update = {
expirationTime,
action,
eagerReducer: null,
eagerState: null,
next: null,
};
......
......
......
scheduleWork(fiber, expirationTime);
}
전재 대상:https://juejin.im/post/5c4c43f5e51d45518c681a69
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.