gpt4 book ai didi

javascript - 使用 `useCallback` 只能与 `useReducer` 一起使用?

转载 作者:行者123 更新时间:2023-12-01 15:55:30 27 4
gpt4 key购买 nike

我有一个使用 React 构建的非常简单的待办事项应用。

App.js看起来像这样

const App = () => {
const [todos, setTodos] = useState(initialState)

const addTodo = (todo) => {
todo.id = id()
todo.done = false
setTodos([...todos, todo])
}

const toggleDone = (id) => {
setTodos(
todos.map((todo) => {
if (todo.id !== id) return todo

return { ...todo, done: !todo.done }
})
)
}

return (
<div className="App">
<NewTodo onSubmit={addTodo} />
<Todos todos={todos} onStatusChange={toggleDone} />
</div>
)
}

export default App

哪里<NewTodo>是呈现输入表单以提交新待办事项和 <Todos /> 的组件是呈现待办事项列表的组件。

现在的问题是,当我切换/更改现有待办事项时,<NewTodo><App /> 后将重新呈现重新渲染并将其传递给 <NewTodo> 的 Prop ,即 addTodo也会改变。因为是新<App />每次渲染其中定义的函数也将是一个新函数。

为了解决这个问题,我首先包装了<NewTodo>React.memo所以当 Prop 没有改变时它会跳过重新渲染。我想用 useCallback获得内存 addTodo这样<NewTodo>不会得到不必要的重新渲染。

  const addTodo = useCallback(
(todo) => {
todo.id = id()
todo.done = false
setTodos([…todos, todo])
},
[todos]
)

但我意识到很明显addTodo取决于 todos这是保存现有待办事项的状态,当您切换/更改现有待办事项时,它会发生变化。所以这个 memoized 函数也会改变。

然后我将我的应用从使用 useState 切换到至 useReducer ,我突然发现我的addTodo不依赖于状态,至少在我看来是这样。



const reducer = (state = [], action) => {
if (action.type === TODO_ADD) {
return [...state, action.payload]
}

if (action.type === TODO_COMPLETE) {
return state.map((todo) => {
if (todo.id !== action.payload.id) return todo
return { ...todo, done: !todo.done }
})
}

return state
}

const App = () => {
const [todos, dispatch] = useReducer(reducer, initialState)

const addTodo = useCallback(
(todo) => {
dispatch({
type: TODO_ADD,
payload: {
id: id(),
done: false,
...todo,
},
})
},
[dispatch]
)

const toggleDone = (id) => {
dispatch({
type: TODO_COMPLETE,
payload: {
id,
},
})
}

return (
<div className="App">
<NewTodo onSubmit={addTodo} />
<Todos todos={todos} onStatusChange={toggleDone} />
</div>
)
}

export default App

如您所见addTodo只是宣布发生在状态上的 Action ,而不是做与状态直接相关的事情。所以这会起作用

  const addTodo = useCallback(
(todo) => {
dispatch({
type: TODO_ADD,
payload: {
id: id(),
done: false,
...todo,
},
})
},
[dispatch]
)

我的问题是,这是否意味着 useCallback永远不能很好地处理包含 useState 的函数?这是使用 useCallback 的能力吗?记住函数被认为是从 useState 切换的好处至 useReducer ?如果我不想切换到 useReducer , 有没有办法使用 useCallbackuseState在这种情况下?

最佳答案

是的。

您需要使用 setTodos 的更新函数语法

const addTodo = useCallback(
(todo) => {
todo.id = id()
todo.done = false
setTodos((todos) => […todos, todo])
},
[]
)

关于javascript - 使用 `useCallback` 只能与 `useReducer` 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62331886/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com