首页 > 解决方案 > React:如何在第一次渲染时跳过 useEffect

问题描述

我正在尝试使用useEffect受控表单组件中的钩子在用户更改表单内容时通知父组件并返回表单内容的 DTO。这是我目前的尝试

const useFormInput = initialValue => {
  const [value, setValue] = useState(initialValue)

  const onChange = ({target}) => {
    console.log("onChange")
    setValue(target.value)
  }

  return { value, setValue, binding: { value, onChange }}
}
useFormInput.propTypes = {
  initialValue: PropTypes.any
}

const DummyForm = ({dummy, onChange}) => {

  const {value: foo, binding: fooBinding} = useFormInput(dummy.value)
  const {value: bar, binding: barBinding} = useFormInput(dummy.value)

  // This should run only after the initial render when user edits inputs
  useEffect(() => {
    console.log("onChange callback")
    onChange({foo, bar})
  }, [foo, bar])

  return (
    <div>
      <input type="text" {...fooBinding} />
      <div>{foo}</div>

      <input type="text" {...barBinding} />
      <div>{bar}</div>
    </div>
  )
}


function App() {
  return (
    <div className="App">
      <header className="App-header">
        <DummyForm dummy={{value: "Initial"}} onChange={(dummy) => console.log(dummy)} />
      </header>
    </div>
  );
}

但是,现在效果是在第一次渲染时运行的,此时初始值是在挂载期间设置的。我该如何避免呢?

以下是加载页面并随后编辑这两个字段的当前日志。我也想知道为什么我会收到缺少依赖项的警告。

onChange callback
App.js:136 {foo: "Initial", bar: "Initial"}
backend.js:1 ./src/App.js
  Line 118:  React Hook useEffect has a missing dependency: 'onChange'. Either include it or remove the dependency array. If 'onChange' changes too often, find the parent component that defines it and wrap that definition in useCallback  react-hooks/exhaustive-deps
r @ backend.js:1
printWarnings @ webpackHotDevClient.js:120
handleWarnings @ webpackHotDevClient.js:125
push../node_modules/react-dev-utils/webpackHotDevClient.js.connection.onmessage @ webpackHotDevClient.js:190
push../node_modules/sockjs-client/lib/event/eventtarget.js.EventTarget.dispatchEvent @ eventtarget.js:56
(anonymous) @ main.js:282
push../node_modules/sockjs-client/lib/main.js.SockJS._transportMessage @ main.js:280
push../node_modules/sockjs-client/lib/event/emitter.js.EventEmitter.emit @ emitter.js:53
WebSocketTransport.ws.onmessage @ websocket.js:36
App.js:99 onChange
App.js:116 onChange callback
App.js:136 {foo: "Initial1", bar: "Initial"}
App.js:99 onChange
App.js:116 onChange callback
App.js:136 {foo: "Initial1", bar: "Initial2"}

标签: javascriptreactjsreact-hooks

解决方案


您可以查看此答案,了解如何忽略初始渲染的方法。此方法用于useRef跟踪第一次渲染。

  const firstUpdate = useRef(true);
  useLayoutEffect(() => {
    if (firstUpdate.current) {
      firstUpdate.current = false;
    } else {
     // do things after first render
    }
  });

至于您收到的警告:

React Hook useEffect 缺少依赖项:'onChange'

钩子调用 ( useEffect(() => {}, [foo]) 中的尾随数组列出了钩子的依赖项。这意味着如果您在挂钩范围内使用一个变量,该变量可以根据组件的更改(例如组件的属性)而更改,则需要在此处列出。


推荐阅读