【发布时间】:2021-09-03 18:55:49
【问题描述】:
我想创建一个自定义挂钩,比如说useTextProcessor(initialText, props)。
这是一种用于存储和操作文本(字符串)的反应状态。
它使用useReducer 来制作累积状态。
代码是这样的:
interface TextEditorProps {
disabled?: boolean
onTextChanged?: (text: string) => void
}
const useTextProcessor = (initialText: string, props: TextEditorProps) => {
const [state, dispatch] = useReducer(textReducerFunc, /*initialState: */{
text : initialText,
props : props, // HACK: a dependency is injected here
});
state.props = props; // HACK: a dependency is updated here
return [
state.text,
dispatch
] as const;
}
有一种黑客方式可以注入props,以便在textReducerFunc 中访问。textReducerFunc 是处理文本的主要函数(取决于动作类型和道具状态)。
我不知道如何将依赖项 props 插入到 textReducerFunc 以专业的反应方式。
如果我在useTextProcessor(initialText, props) 中声明了textReducerFunc,
是的,我可以访问 props,但请稍等,因为它是一个子函数,所以每次调用 useTextProcessor 都会重新创建子函数。
这使得useReducer 在下一次渲染中执行textReducerFunc 两次。
Ut 正在制作 onTextChanged 也将执行两次。
用useCallback 包装不会有任何效果,因为onTextChanged 接受任何函数(可能是静态或内联函数)。每次渲染时,内联函数的引用总是不同的。
这里是textReducerFunc 作品的详细信息:
interface TextState {
props: TextEditorProps // holds my hack
text: string // the actual data to be processed
}
interface TextAction {
type: 'APPEND'|'UPPERCASE'
payload?: string
}
const textReducerFunc = (state: TextState, action: TextAction) => {
const props = state.props;
if (props.disabled) return state; // disabled => no change
switch(action.type) {
case 'APPEND':
const appendText = state.text + action.payload;
props.onTextChanged?.(appendText); // notify the text has been modified
return {...state, text: appendText};
case 'UPPERCASE':
const upperText = state.text.toUpperCase();
props.onTextChanged?.(upperText); // notify the text has been modified
return {...state, text: upperText};
default:
return state; // unknown type => no change
} // switch
}
useTextProcessor的用法:
export default function TxtEditor(props: TextEditorProps) {
const [text, dispatch] = useTextProcessor('hello', props);
return (
<div>
<div>
{text}
</div>
<button onClick={() => dispatch({type: 'APPEND', payload: ' world'})}>append 'world'</button>
<button onClick={() => dispatch({type: 'UPPERCASE'})}>uppercase</button>
</div>
)
}
你能建议我如何使用 useReducer 与依赖没有任何黑客?
【问题讨论】:
标签: javascript reactjs typescript react-hooks