reactjs - React reducer 必须是纯函数吗?

标签 reactjs typescript react-hooks pure-function

我写了一个 UI 元素作为函数组件,它使用 React 的 userReducer钩子(Hook),它似乎运行没有错误。

useReducer引用我写的一个函数(想象中称为 reducer ):

  const [state, dispatch] = React.useReducer(reducer, inputData,
    (inputData) => initialState(inputData));

state由reducer函数输入和输出的数据;并且有依赖于 state 的“托管”UI 元素, 像...

  return (
    <div>
      <div>
        {state.elements.map(getElement)}
      </div>
      <ShowHints hints={state.hints} inputValue={state.inputValue} />
    </div>
  );

...这是正常的。

我担心的是 reducer功能不纯。

  • 它的行为仅取决于它的输入参数——因此使用相同的输入参数调用它两次具有相同的结果。
  • 但是它会产生副作用,它不仅会返回新状态

副作用是有一个 <input>状态由以下之一控制的元素:

const inputRef = React.createRef<HTMLInputElement>();

<input>控制只是半管理的,像这样:

<input type="text" ref={inputRef} onKeyDown={handleKeyDown} onChange={handleChange}

onKeyDownonChange事件是发送给 reducer 的 Action (这很好)但是 reducer 被传递给了 HTMLInputElement实例(即 inputRef.current 值)作为输入参数,reducer 设置该 HTMLInputElement 的属性改变它的状态——而不是 <input>作为一个完全托管的组件,其内容由 reducer 输出的状态定义。

<input> 的原因element isn't fully-managed 是我需要控制 start 内的选择范围(即 end<input> )而不仅仅是它的文本值。

问题:

  • reducer 函数以这种方式不纯是否可以(例如,尽管有问题或值得注意但没有错误)?
    • 它只依赖于它的输入参数,因此是可重复的
    • 但它会改变某些东西(即 inputRef.current 属性)并返回新的 state值(value)
  • reducer 有没有其他方法来控制 startend <input type="text"> 的属性元素,例如一种定义 <input> 的方法元素使得它的 startend值由他控制 state由 reducer 返回?

(我认为 @Fyodor's answer below 回答了第二个问题,我仍然不确定第一个问题)。


什么决定了要在 HTML 元素上设置的值?使用信息是否传入或包含逻辑?

组件的设计和源代码是shown here ,而且很长。

这是一个复杂的“组件”,使用多个元素实现——两个 <div> s,几个<span> s,一些可点击的 <svg> s 和 <input>元素。

reducer 是给定的,作为它的输入参数:

  • 之前的“状态”
  • 当前<input>实例(它可以从中读取 <input> 的当前状态)
  • 事件处理程序创建的“ Action ”

几个事件处理程序或操作中的两个是 onKeyDownonChange <input>的事件所以 <input> 的当前状态当有一个事件改变了 <input> 的状态时,它被传递给 reducer .

最佳答案

从技术上讲,reducer 可能会产生不同的副作用。我不认为这是一个好的做法,至少是因为关注点分离不好(预计 reducer 只根据 Action 产生新状态,而不是改变其他东西)。 (很抱歉提出我自己的意见,似乎使用了 useReducer 中的副作用,例如 here )。同样在 Redux 中,所有副作用都移到了 action creators。 .

对于您的具体问题,我可能会建议将 inputRef 突变移动到单独的 useEffect Hook ,这反过来又取决于如下状态

useEffect (() => {
    inputRef.currect // do work with inputRef
}, [state]); // make dependent from state

这里是 sample使 useEffect 依赖于 state

您还可以将 useEffect 移动到 custom hook使代码像下面一样可重用(未经测试,用作提示)

function mutateRef (inputRef: React.RefObject<HTMLInputElement>, state: /* type of state */) {
    useEffect (() => {
        inputRef.currect // do work with inputRef
    }, [state, inputRef]);
}

关于reactjs - React reducer 必须是纯函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57142137/

相关文章:

javascript - React Native : Error :"Cannot read property ' name' of undefined,“虽然包含名称的对象不是未定义的

reactjs - 在 React 中关注(滚动到)一个 DIV 元素

html - 如何修复 Angular Materials 不起作用的错误

javascript - 为什么 componentDidMount 在 componentWillUnmount 之后运行?

reactjs - 使用 React Hook 时,来自 MediaRecorder 的中间数据丢失

javascript - React js 表单字段名称和引用连接

css - 样式组件也可以在服务器上呈现吗?

typescript - 如何在 typescript 中将可区分联合与函数重载相结合

javascript - 对象的 typescript 定义,用作数组

reactjs - 使用redux-form按下下一个键盘按钮后如何使用useRef Hook 选择下一个TextInput