
function Todo() {
const [todos, push] = useState([]);
return (
<>
<Input submit={todo => push(todos => [...todos, todo])} />
<OrderList list={todos} />
</>
);
};
function Input({ submit }) {
const [value, setValue] = useState("");
return (
<>
<input value={value} onChange={e => setValue(e.target.value)} />
<button
onClick={() => {
submit(value);
setValue("");
}}
>
submit
</button>
</>
);
}
function OrderList({ list }) {
return (
<ol>
{list.map(item => (
<li>{item}</li>
))}
</ol>
);
}
function App() { return <Todo /> };
ReactDOM.render(<App />, container);
input 입력
<input value={value} onChange={e => setValue(e.target.value)} />
-> onChange에 의해 state값이 변경
-> setState가 호출되면 react 내부적으로 dispatchAction이 호출
-> updateQueue에 렌더링해야한다고 push함
-> beginwork를 통해 updateFunctionComponent를 호출
-> 이 때 업데이트된 fiber를 workInProgress에 적용시킴
-> input 탐색 시 useEffect를 호출하기 되므로 EffectTag에 passive가 달음
-> workInProgress Tree를 다 그리면 fiber에서 react Element로 변경하여야 하고, side Effect List를 만들어야함
-> completeWork를 통해 input props가 변경되었다는 사실을 알게됨 ex) value, children
if (returnFiber.firstEffect === null) {
returnFiber.firstEffect = workInProgress.firstEffect;
}
if (workInProgress.lastEffect !== null) {
if (returnFiber.lastEffect !== null) {
returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;
}
returnFiber.lastEffect = workInProgress.lastEffect;
}
const effectTag = workInProgress.effectTag;
if (effectTag > PerformedWork) {
if (returnFiber.lastEffect !== null) {
returnFiber.lastEffect.nextEffect = workInProgress;
} else {
returnFiber.firstEffect = workInProgress;
}
returnFiber.lastEffect = workInProgress;
}
-> input element를 변경하였고, 이후 commit phase에서 소비해야할 effectList를 만듬
-> 현재 returnFiber = Input / workInProgress(이하 WIP라고 칭함) = input
Input의 firstEffect, lastEffect = null
input의 firstEffect, lastEffect = nullInput의 firstEffect가 null이므로
Input.firstEffect = input.firstEffect 연결하는데 하지만, input의 firstEffect가 null이므로 Input.firstEffect = nullinput.lastEffect가 null이므로 분기 패스
input의 effect Tag가 존재하며, Input.lastEffect가 null이므로
Input.firstEffect = input / Input.lastEffect = input
현재까지의 Effect List
Input - input(FirstEffect & lastEffect)
-> returnFiber = Input / WIF = button
현재 Input.firstEffect = input / Input.lastEffect = input
Input.firstEffect = input이므로 첫번째 분기 제외
button.lastEffect = null이므로 두번째 분기 제외button에는 effectTag가 존재하고, Input.lastEffect = input이므로
input.nextEffect = button을 할당하고
Input.lastEffect = button을 할당
현재까지의 Effect List
Input - input(firstEffect) - button(lastEffect)
-> returnFiber = Todo / WIP = Input
현재 Todo.firstEffect / lastEffect = null
Input.firstEffect = input / Input.lastEffect = button첫번째 분기 Todo.firstEffect = null이므로
Todo.firstEffect = Input.firstEffect = input으로 할당
두번째 분기 Input.lastEffect가 존재하고, Todo.lastEffect = null이므로 Todo.lastEffect = input.lastEffect = button 할당정리
Todo - input(firstEffect) - button(lastEffect)
Input - input(firstEffect) - button(lastEffect)Input은 effect tag를 갖고 있고, Todo.lastEffect = button이므로
Todo.lastEffect.nextEffect = Input을 할당
Todo.lastEffect = Input 할당
즉 Todo - input(firstEffect) - button - Input(lastEffect)
위부터는 effect Tag가 존재하지 않기때문에 지속적으로 firstEffect와 lastEffect만 부모로 옮겨주는 것만 함.
최종 EffectList => input(firstEffect) - button - Input(lastEffect)