<aside> 💡 상태는 왠만하면 사용할곳과 가장 가까운 곳에 위치해야한다 + 언제나 React.state가 필요할까?

</aside>

TL;DR

불필요한 리랜더링을 해결하고싶을 땐 상태를 사용하는 가장 가까운 곳에 두는것이 편하다.

아니, 최대한 상태를 사용하지 않는 것이 좋다.


Slow Form

[Form]

function SlowForm() {

	// manage input field values
	const [fieldValues, setFieldValues] = useReducer(
    (state, action) => ({
      ...state,
      ...action,
    }),
    initialFieldValues,
  );

	// manage input field is focused
  const [touchedFields, setTouchedFields] = useReducer(
    (state, action) => ({
      ...state,
      ...action,
    }),
    initialTouchedFields,
  );
	const [wasSubmitted, setWasSubmitted] = useState(false);

	// validate form & submit
	function handleSubmit(event) {
    event.preventDefault();
    const formIsValid = fieldNames.every(name => !getFieldError(fieldValues[name]));
    setWasSubmitted(true);
    if (formIsValid) {
      console.log(`Slow Form Submitted`, fieldValues);
    };
  };

	// change input value
	function handleChange(event) {
    setFieldValues({ [event.currentTarget.name]: event.currentTarget.value });
  };

	// check input on Blur
  function handleBlur(event) {
    setTouchedFields({ [event.currentTarget.name]: true });
  };

	return (
		<form noValidate onSubmit={handleSubmit}>
			{fieldNames.map(name => (
			<SlowInput
				key={name} 
				name={name} 
				fieldValues={fieldValues}
			  touchedFields={touchedFields} 
				wasSubmitted={wasSubmitted}
			  handleChange={handleChange} 
				handleBlur={handleBlur} />
			))}
		  <button type="submit">Submit</button>
		</form>
	) 
}

위 방식은 Form Component 에서 모든 input field를 관리하는 방식이다.

적어도 내가 지금까지 본 많은 Form component들이 위와같은 방식으로 되어있는데,

이 방식은 한가지 큰 단점이 있다.

바로 모든 유저의 interaction 하나하나에 Form 전체의 리랜더링이 일어난다는 것인데,

Memoization도 위 문제를 근본적으로 해결할 수 없다.

왜냐면 props로 넘기는 fieldValues 자체가 유저의 타이핑 하나하나에 반응하여 리랜더링 되기 때문이다.

만약 Form이 심플하다면 큰문제는 없다. 리액트에서 리랜더링은 당연한 현상이고,

작은 리소스를 리랜더링 하는 행위는 유저에게 유의미한 불편하기 주기 힘들것이기 때문이다.

하지만 우리의 Form은 아래와 같은 이유로 쉽게 복잡해질 수 있다.