알게 모르게 클로저의 개념을 많이 사용하고 있다.
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");