React reducer 必须是纯函数吗?

Must a React reducer be a pure function?

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

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

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

state个数据是reducer函数的输入输出;并且有 "managed" UI 元素依赖于 state,类似于 ...

  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 的动作(这很好)但是 reducer 被传递给 HTMLInputElement 实例(即 inputRef.current 值) 作为输入参数,reducer 设置 HTMLInputElement 的属性来改变它的状态——也就是说 <input> 是一个完全托管的组件,其内容由输出的状态定义减速器。

<input>元素没有完全管理的原因是我需要控制[=20=内的选择范围(即startend) ] 而不仅仅是它的文本值。

问题:

(我认为回答了第二个问题,我对第一个问题仍然不确定。


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

该组件的设计和源代码shown here,相当长。

这是一个复杂的 "component",它使用多个元素实现 -- 几个 <div>s、几个 <span>s、一些可点击的 <svg>s,以及<input> 元素。

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

几个事件处理程序或操作中的两个是 <input>onKeyDownonChange 事件,因此 <input> 的当前状态被传递到当有一个事件改变 <input>.

的状态时,reducer

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

对于你的具体问题,我可能会建议将 inputRef 突变移动到单独的 useEffect 钩子,这又取决于下面的状态

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]);
}