reactjs 在useImperativeHandle函数中未定义let变量

zbdgwd5y  于 2023-01-08  发布在  React
关注(0)|答案(1)|浏览(194)

我在React Native(Expo)下的. web.js文件中使用lottie-web包。
我的问题是在useImperativeHandle的函数中let变量anim没有定义。在useEffect中,anim工作得很好。例如,如果我anim.play在useEffect初始化之后立即访问www.example.com(),它工作。但是在命令式的play()函数中,它不工作。
在我的父组件中,我使用useRef创建了一个ref,并将其传递给组件

const lottieAnim = useRef(null);

--

let anim;
useEffect(() => {
  const lottieOptions = {
    container: divContainer.current,
    renderer: 'svg',
    loop,
    autoplay,
    segments: segments !== false,
    animationData,
    rendererSettings,
  };
  anim = lottie.loadAnimation({ ...lottieOptions, ...options });
  // anim.play(); works here 

  if (onAnimationFinish) {
    anim.addEventListener('complete', onAnimationFinish);
  }
}, []);

useImperativeHandle(ref, () => ({
  stop() {
    anim.stop();
  },
  pause() {
    anim.pause();
  },
  play() {
    anim.play();
    // anim is undefined
  },
  setSpeed(s) {
    anim.setSpeed(s);
  },
  setDirection(d) {
    anim.setDirection(d);
  },
  playSegments(s) {
    anim.playSegments(s);
  },
}));
nbewdwxp

nbewdwxp1#

2023年更新

我创建了一个包,用于连接第三方包,以便通过useImperativeHandler以更简单的方式做出React,您可能会发现它很有用,而且更易于使用😊。
react-aptor
这是因为React在useImperativeHandle中创建API函数时不知道anim是什么(由于闭包和react更新策略不会通过改变变量来触发任何更新)。有一些方法可以处理这个问题,毕竟,这是个人意见,我会使用这样的东西,对我来说最好。

添加GetApi函数

// hanlder.js
const stop = anim => anim.stop()
// api.js
const getAPI = anim => () => ({
  stop: stop.bind(this, anim),
  // or simply
  setSpeed: s => anim.setSpeed(s),

  // you can mock APIs here if anim is null or throw an Error
});

anim存储在某个状态中

anim存储在仅用于第一次渲染的状态中,并在getApiuseEffect的依赖性数组中使用它

const [anim, setAnim] = React.useState(null);

React.useEffect(() => {
  // initialization part
}, []);

React.useImperativeHandle(ref, getAPI(anim), [anim]);

相关问题