useState

알게 모르게 클로저의 개념을 많이 사용하고 있다.

function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState('');

  const addTodo = () => {
    if (input.trim() !== '') {
      setTodos([...todos, { text: input, completed: false }]);
      setInput('');
    }
  };

  const toggleTodo = (index) => {
    const newTodos = [...todos];
    newTodos[index].completed = !newTodos[index].completed;
    setTodos(newTodos);
  };

  const removeTodo = (index) => {
    const newTodos = todos.filter((_, i) => i !== index);
    setTodos(newTodos);
  };

  return (
    <div>
      <h1>Todo List</h1>
      <input 
        type="text" 
        value={input} 
        onChange={(e) => setInput(e.target.value)}
      />
      <button onClick={addTodo}>Add Todo</button>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>
            <span 
              style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
              onClick={() => toggleTodo(index)}
            >
              {todo.text}
            </span>
            <button onClick={() => removeTodo(index)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TodoApp;

useState() 로 반환된 값을 어떻게 계속 사용할 수 있을까? 추가적으로 반환된 state의 값을 직접 변경할 수 없고 setState를 통해서만 변경할 수 있다는 점. 또한 setState를 실행하면 어떻게 독립적으로 보이는 state의 값이 변경될까?

이는 클로저로 구현되어 있기 때문이다.

간단히 useState를 구현해보겠다.

function useState(initVal) {
  let _val = initVal
  const state = () => _val
  const setState = (newVal) => {
    _val = newVal
  }

  return [state, setState]
}

const [count, setCount] = useState(1)
console.log(count()) // 1
setCount(2)
console.log(count()) // 2

심볼형

let id = Symbol();
let id = Symbol("hi");