使用 React 和 Redux,如何在 redux-thunk 成功完成后清除输入字段?
Using React and Redux, how would you clear an input field after a successful redux-thunk completion?
假设您正在使用 react
和 redux
,并且页面上有以下元素:
- 要写东西的输入框
- 用于将文本异步写入数据库的保存按钮
预期的流程是保存按钮应该调度一个 save
redux thunk 来处理保存的异步行为。到目前为止,还不错。
但是还有一个额外的棘手要求:
- 保存成功后,应清空输入。
我认为有几种方法可以解决这个问题:
选项 1
- 将受控输入状态添加到您的 Redux 存储
这是最简单的一个。基本上,您会将 input
状态添加到您的 Redux 存储中,当您发送 SAVE_SUCCESS
操作时,您的 reducer 将响应如下内容:
SAVE_SUCCESS(state, action) {
state.inputValue = '';
}
这样做的缺点是你必须在每次击键时发送一个动作,这会淹没你的 Redux devTools 检查器。
选项 2
- 使用 React 本地状态控制输入
- 将
clearInput
函数(使用 useCallback
)传递到您的保存 thunk
像这样:
const [inputValue, setInputValue] = useState('initialVale');
const clearInput = useCallback(() => setInputValue(''),[]);
const onClick = dispatch(saveThunk({clearInput});
所以,从 thunk 你会做这样的事情:
const { clearInput } = thunkProps;
await saveToDB();
clearInput(); // THIS COMES FROM THE thunkProps
选项 3
- 与选项 2 相同,但输入不受控制(因此,根本没有状态)
- 将输入的 ref 元素传递给你的 thunk
所以,从 thunk 你会做这样的事情:
const { inputRef } = thunkProps;
await saveToDB();
inputRef.current.value = '';
问题
你会选择哪一个,为什么?还有,有没有我不知道的更好的方法?
我会等待组件中 thunk 的承诺,并在那里设置组件状态,如我们的教程所示:
- https://redux.js.org/tutorials/fundamentals/part-7-standard-patterns#thunks-and-promises
- https://redux.js.org/tutorials/essentials/part-5-async-logic#checking-thunk-results-in-components
示例:
const handleKeyDown = async e => {
// If the user pressed the Enter key:
const trimmedText = text.trim()
if (e.which === 13 && trimmedText) {
// Create and dispatch the thunk function itself
setStatus('loading')
// Wait for the promise returned by saveNewTodo
await dispatch(saveNewTodo(trimmedText))
// And clear out the text input
setText('')
setStatus('idle')
}
}
我想马克的答案应该是推荐的。但是,作为另一种方法(并且作为将来给自己的注释),如果您没有使用 createAsyncThunk
函数来创建您的 thunk,您可以指定一个要从您创建的常规 thunk 返回的值你自己。
这是一个非常粗略的示例,但可以解决问题:
import { AnyAction, ThunkAction } from '@reduxjs/toolkit';
type MaybeSuccess = { success: boolean }
type AppThunkMaybeSuccess = ThunkAction<Promise<MaybeSuccess>, RootState, unknown, AnyAction>;
export const someThunk = (): AppThunkMaybeSuccess => async (dispatch, getState) => {
try {
dispatch(SOME_THUNK_START());
const data = await doSomeAsyncStuff(...);
dispatch(SOME_THUNK_SUCCESS({ data }));
return ({ success: true });
}
catch(err) {
const error = err as Error;
dispatch(SOME_THUNK_FAILURE();
return ({ success: false });
}
}
然后,在您的组件(发送 thunk 的组件)上,您可以:
const handleSave = useCallback(async () => {
const { success } = await dispatch(saveThunk());
if (success) {
setInputValue('');
}
},[]);
假设您正在使用 react
和 redux
,并且页面上有以下元素:
- 要写东西的输入框
- 用于将文本异步写入数据库的保存按钮
预期的流程是保存按钮应该调度一个 save
redux thunk 来处理保存的异步行为。到目前为止,还不错。
但是还有一个额外的棘手要求:
- 保存成功后,应清空输入。
我认为有几种方法可以解决这个问题:
选项 1
- 将受控输入状态添加到您的 Redux 存储
这是最简单的一个。基本上,您会将 input
状态添加到您的 Redux 存储中,当您发送 SAVE_SUCCESS
操作时,您的 reducer 将响应如下内容:
SAVE_SUCCESS(state, action) {
state.inputValue = '';
}
这样做的缺点是你必须在每次击键时发送一个动作,这会淹没你的 Redux devTools 检查器。
选项 2
- 使用 React 本地状态控制输入
- 将
clearInput
函数(使用useCallback
)传递到您的保存thunk
像这样:
const [inputValue, setInputValue] = useState('initialVale');
const clearInput = useCallback(() => setInputValue(''),[]);
const onClick = dispatch(saveThunk({clearInput});
所以,从 thunk 你会做这样的事情:
const { clearInput } = thunkProps;
await saveToDB();
clearInput(); // THIS COMES FROM THE thunkProps
选项 3
- 与选项 2 相同,但输入不受控制(因此,根本没有状态)
- 将输入的 ref 元素传递给你的 thunk
所以,从 thunk 你会做这样的事情:
const { inputRef } = thunkProps;
await saveToDB();
inputRef.current.value = '';
问题
你会选择哪一个,为什么?还有,有没有我不知道的更好的方法?
我会等待组件中 thunk 的承诺,并在那里设置组件状态,如我们的教程所示:
- https://redux.js.org/tutorials/fundamentals/part-7-standard-patterns#thunks-and-promises
- https://redux.js.org/tutorials/essentials/part-5-async-logic#checking-thunk-results-in-components
示例:
const handleKeyDown = async e => {
// If the user pressed the Enter key:
const trimmedText = text.trim()
if (e.which === 13 && trimmedText) {
// Create and dispatch the thunk function itself
setStatus('loading')
// Wait for the promise returned by saveNewTodo
await dispatch(saveNewTodo(trimmedText))
// And clear out the text input
setText('')
setStatus('idle')
}
}
我想马克的答案应该是推荐的。但是,作为另一种方法(并且作为将来给自己的注释),如果您没有使用 createAsyncThunk
函数来创建您的 thunk,您可以指定一个要从您创建的常规 thunk 返回的值你自己。
这是一个非常粗略的示例,但可以解决问题:
import { AnyAction, ThunkAction } from '@reduxjs/toolkit';
type MaybeSuccess = { success: boolean }
type AppThunkMaybeSuccess = ThunkAction<Promise<MaybeSuccess>, RootState, unknown, AnyAction>;
export const someThunk = (): AppThunkMaybeSuccess => async (dispatch, getState) => {
try {
dispatch(SOME_THUNK_START());
const data = await doSomeAsyncStuff(...);
dispatch(SOME_THUNK_SUCCESS({ data }));
return ({ success: true });
}
catch(err) {
const error = err as Error;
dispatch(SOME_THUNK_FAILURE();
return ({ success: false });
}
}
然后,在您的组件(发送 thunk 的组件)上,您可以:
const handleSave = useCallback(async () => {
const { success } = await dispatch(saveThunk());
if (success) {
setInputValue('');
}
},[]);