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
函数不纯。
- 它的行为仅取决于它的输入参数——因此使用相同的输入参数调用它两次具有相同的结果。
- 但是它会产生副作用,它不仅return新状态
副作用是有一个 <input>
元素的状态由以下之一控制:
const inputRef = React.createRef<HTMLInputElement>();
<input>
控件只是半托管的,像这样:
<input type="text" ref={inputRef} onKeyDown={handleKeyDown} onChange={handleChange}
onKeyDown
和 onChange
事件是分派给 reducer 的动作(这很好)但是 reducer 被传递给 HTMLInputElement
实例(即 inputRef.current
值) 作为输入参数,reducer 设置 HTMLInputElement
的属性来改变它的状态——也就是说 <input>
是一个完全托管的组件,其内容由输出的状态定义减速器。
<input>
元素没有完全管理的原因是我需要控制[=20=内的选择范围(即start
和end
) ] 而不仅仅是它的文本值。
问题:
- reducer 函数以这种方式不纯是否可以(例如,尽管有问题或值得注意但没有错误)?
- 它只依赖于它的输入参数,因此是可重复的
- 但它会改变某些东西(即
inputRef.current
属性)以及 return 新的 state
值
- reducer 是否有另一种方法来控制
<input type="text">
元素的 start
和 end
属性,例如一种定义 <input>
元素的方法,使其 start
和 end
值由他 state
return 由减速器控制?
(我认为回答了第二个问题,我对第一个问题仍然不确定。
什么决定了要在 HTML 元素上设置的值?传入的使用信息是否包含逻辑?
该组件的设计和源代码shown here,相当长。
这是一个复杂的 "component",它使用多个元素实现 -- 几个 <div>
s、几个 <span>
s、一些可点击的 <svg>
s,以及<input>
元素。
reducer 是给定的,作为它的输入参数:
- 上一个"state"
- 当前
<input>
实例(它可以从中读取 <input>
的当前状态)
- 由事件处理程序创建的"action"
几个事件处理程序或操作中的两个是 <input>
的 onKeyDown
和 onChange
事件,因此 <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]);
}
我写了一个 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
函数不纯。
- 它的行为仅取决于它的输入参数——因此使用相同的输入参数调用它两次具有相同的结果。
- 但是它会产生副作用,它不仅return新状态
副作用是有一个 <input>
元素的状态由以下之一控制:
const inputRef = React.createRef<HTMLInputElement>();
<input>
控件只是半托管的,像这样:
<input type="text" ref={inputRef} onKeyDown={handleKeyDown} onChange={handleChange}
onKeyDown
和 onChange
事件是分派给 reducer 的动作(这很好)但是 reducer 被传递给 HTMLInputElement
实例(即 inputRef.current
值) 作为输入参数,reducer 设置 HTMLInputElement
的属性来改变它的状态——也就是说 <input>
是一个完全托管的组件,其内容由输出的状态定义减速器。
<input>
元素没有完全管理的原因是我需要控制[=20=内的选择范围(即start
和end
) ] 而不仅仅是它的文本值。
问题:
- reducer 函数以这种方式不纯是否可以(例如,尽管有问题或值得注意但没有错误)?
- 它只依赖于它的输入参数,因此是可重复的
- 但它会改变某些东西(即
inputRef.current
属性)以及 return 新的state
值
- reducer 是否有另一种方法来控制
<input type="text">
元素的start
和end
属性,例如一种定义<input>
元素的方法,使其start
和end
值由他state
return 由减速器控制?
(我认为
什么决定了要在 HTML 元素上设置的值?传入的使用信息是否包含逻辑?
该组件的设计和源代码shown here,相当长。
这是一个复杂的 "component",它使用多个元素实现 -- 几个 <div>
s、几个 <span>
s、一些可点击的 <svg>
s,以及<input>
元素。
reducer 是给定的,作为它的输入参数:
- 上一个"state"
- 当前
<input>
实例(它可以从中读取<input>
的当前状态) - 由事件处理程序创建的"action"
几个事件处理程序或操作中的两个是 <input>
的 onKeyDown
和 onChange
事件,因此 <input>
的当前状态被传递到当有一个事件改变 <input>
.
从技术上讲,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]);
}