传递useState setter函数作为回调

时间:2020-09-19 22:51:24

标签: javascript reactjs react-component

我在React组件中使用useState,并且我希望将setter作为回调的一部分传递给另一个函数(该另一个函数处理组件中无法访问的某些逻辑)。

这是简化的代码:

function init(canvas, cb) {
    ...
    // Call cb(...) based on internal logic
}

function MyComponent () {
    const canvasRef = useRef(null);
    const [x, setX] = useState(null);
    useEffect(() => {
        const canvas = canvasRef.current
        init(canvas, function (v) {
            console.log(v);
            setX(v);
        });
    }, []);
    return <div>
        <canvas ref={canvasRef} width="500" height="300"></canvas>
        <div}>{x}</div>
    </div>
}

问题是,除了第一次(当x不再是x时)之外,调用回调时null的值不会更新。

我知道它已被调用,并且我知道x已更新,因为我可以在控制台中看到日志。 就像设置器setX无法正常工作或组件无法检测到x已被更新一样。

我做错了什么?

2 个答案:

答案 0 :(得分:1)

对我有用。到底是什么问题?你能举个例子吗?

function init(canvas, cb) {
      cb(100)
}



function MyComponent () {
    const canvasRef = React.useRef(null);
    const [x, setX] = React.useState(null);
    
    React.useEffect(() => {
        const canvas = canvasRef.current
        
        init(canvas, function (v) {
            console.log(v);
            setX(v);
        });
    }, []);
    
    function handleOnClick() {
      init(canvasRef.current, function (v) {
        setX(prev => prev + v)
      })
    }
    
    return (
      <div>
        <button onClick={handleOnClick}>Change prop x</button>
        <div>{x}</div>
        <canvas ref={canvasRef} width="500" height="100" />
        
      </div>
    )
}

ReactDOM.render(<MyComponent />, document.querySelector('#root'))
canvas {
  background: pink;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>

答案 1 :(得分:1)

在此repl中,我试图做类似的事情。


import * as React from 'react'
import * as ReactDOM from 'react-dom'

function foo (cb, value){
  return cb(value);
}

function App (props){
  const [x, setX] = React.useState(0);

  const handleClick = v => {
    setX(v);
  }

  return(
    
    <div> 
      {x? x: "Hello World"} 
    
      <input type="button" value="Press Me" onClick={() => foo(handleClick, x+1)} /> 
    </div>
  )
}

ReactDOM.render(
  <App />
  ,
  document.getElementById('root')
);


每个状态更改仅调用一次使用效果,我看不到您在组件内部调用状态更新的位置。

如果您要从另一个完全不同的位置更改此组件的状态,则建议您使用提供程序或HOC