如何将参数传递给反应中的事件侦听器?

How can I pass arguments to event listeners in react?

我正在努力使我的代码简洁易读。所以我决定创建一个自定义挂钩来将我的 useState 存储在那里。然后我创建了一个新文件来存储我的事件监听器。现在,我有三个文件:Page.jsuseStates.jsListeners.js.

问题是我不能在事件侦听器中使用我的状态。


我试图将我的状态存储在 useStates.js 中的全局范围变量中,并使用 getter 传递它们。但它不起作用,因为更新状态并没有改变页面(但它确实重新呈现)。


useStates.js:

import react, { useState } from 'react';

export default () => {
  const [myState, setMyState] = useState(false);
  return { myState, setMyState };
}

Page.js:

import react from 'react';
import useStates from './useStates';
import { someActionListener } from './listeners';

export default () => {
  const states = useStates();

  return <SomeComponent
            somProp={states.myState}
            onSomeAction={ someActionListener } />
}

Listeners.js:

export const someActionListener = (e) => {
  // This should be done
  states.setMyState(!states.myState);
} 

您可以将 states 传递给侦听器:

export const someActionListener = (e, states) => {
  // This should be done
  states.setMyState(!states.myState);
}

...

<SomeComponent
  somProp={states.myState}
  onSomeAction={e => someActionListener(e, states)}
/>

或者柯里化 states 值,导致更干净 UI,它保存了匿名函数回调:

export const someActionListener = states =>  e => {
  // This should be done
  states.setMyState(!states.myState);
}

...

<SomeComponent
  somProp={states.myState}
  onSomeAction={someActionListener(states)}
/>

我建议调整动作侦听器以接收回调。无论如何,事件监听器通常都会这样做。柯里化函数是关闭回调和 return 事件侦听器回调的简单方法。这将状态和状态更新与事件侦听器逻辑分离,允许 React 组件使用两者来保持对状态及其更新方式的控制。

export const someActionListener = (callback) => (e) => {
  // This should be done
  callback();
}

将状态更新函数作为回调传入。

export default () => {
  const states = useStates();

  return (
    <SomeComponent
      somProp={states.myState}
      onSomeAction={someActionListener(
        () => states.setMyState(!states.myState))
      )}
    />
  );
}

或者使用功能状态更新,因为您正在切换状态值。这是为了避免在回调中包含陈旧的状态。

<SomeComponent
  somProp={states.myState}
  onSomeAction={someActionListener(
    () => states.setMyState(states => ({
       ...states
       myState: !states.myState
    })
  }
/>