简体   繁体   English

React refs 在 useCallback 中如何表现?

[英]How do React refs behave inside useCallback?

I wouldn't expect the following React app to work properly, but it does.我不希望下面的 React 应用程序能正常工作,但确实如此。 I'd expect the useCallback hook to capture and preserve the initial value of the ref.我希望 useCallback 钩子能够捕获并保留 ref 的初始值。 I understand that the ref couldn't be listed in the dependency array so maybe this is a special case only intended for refs?我知道 ref 无法在依赖数组中列出,所以这可能是仅用于 refs 的特殊情况?

Why isn't the content of newTodoRef.current.value captured by useCallback just once when App first renders?为什么在 App 首次渲染时,useCallback 不会只捕获一次 newTodoRef.current.value 的内容?

import React, { useCallback, useReducer, useRef } from 'react';

type Todo = { id: number, text: string }
type ActionType = { type: 'ADD', text: string} | { type: 'REMOVE', id: number}

const todoReducer = (state: Todo[], action: ActionType) => {
    switch(action.type) {
        case 'ADD': return [ ...state, { id: state.length, text: action.text }]
        case 'REMOVE': return state.filter(({ id }) => id !== action.id) // this is buggy, but that's beside the point
        default: throw new Error()
    }
}

function App() {
    const [todos, dispatch] = useReducer(todoReducer, [])

    const newTodoRef = useRef<HTMLInputElement>(null)

    const onAddTodo = useCallback(() => {
        if (newTodoRef.current) {
            dispatch({ type: "ADD", text: newTodoRef.current.value })
            newTodoRef.current.value = ''
        }
    }, [])

    return (
        <div>
            {todos.map(todo => (
                <div key={todo.id}>
                    {todo.text}
                    <button onClick={() => dispatch({ type:"REMOVE", id: todo.id })}>Remove</button>
                </div>
            ))}
            <input type="text" ref={newTodoRef}/>
            <button onClick={onAddTodo}>ADD</button>
        </div>
    )
}

export default App;

Why isn't the content of newTodoRef.current.value captured by useCallback just once when App first renders?为什么在 App 首次渲染时,useCallback 不会只捕获一次 newTodoRef.current.value 的内容?

The reference to the top level object, newTodoRef , is captured in this way.以这种方式捕获对顶级newTodoRef的引用 newTodoRef 。 The reason this works out fine is that the ref is a mutable object, and the same object on every render.这很好的原因是 ref 是一个可变的 object,并且每个渲染都使用相同的 object。 Once react has created the div element on the page, it will mutate newTodoRef , changing its .current property to the element.一旦 react 在页面上创建了 div 元素,它将改变newTodoRef ,将其.current属性更改为该元素。 Then later, you access newTodoRef , which is still the same object, and you get it's .current property.稍后,您访问newTodoRef ,它仍然是相同的 object,您将获得它的.current属性。 The property has changed in the meantime, but the object has not.同时属性发生了变化,但 object 没有。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM