我目前正在使用注册表单,以下是我的代码段:
const Signup = () => {
const [username, setUsername] = useState('')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [passwordConfirmation, setPasswordConfirmation] = useState('')
const clearState = () => {
setUsername('')
setEmail('')
setPassword('')
setPasswordConfirmation('')
}
const handleSubmit = signupUser => e => {
e.preventDefault()
signupUser().then(data => {
console.log(data)
clearState() // <-----------
})
}
return <JSX />
}
export default Signup
每种状态都用于表格的受控输入。
基本上,我想做的是在用户成功注册后,希望状态恢复为初始状态并清除字段。
在clearState
中将每个状态手动设置回空字符串是非常必要的,我想知道React是否提供了一种方法或函数来将状态重置为其初始值?
答案 0 :(得分:6)
遗憾的是,没有内置的方法可以将状态设置为其初始值。
您的代码看起来不错,但是如果要减少所需的功能,可以将整个表单状态放在单个状态变量对象中,然后重置为初始对象。
示例
const { useState } = React;
function signupUser() {
return new Promise(resolve => {
setTimeout(resolve, 1000);
});
}
const initialState = {
username: "",
email: "",
password: "",
passwordConfirmation: ""
};
const Signup = () => {
const [
{ username, email, password, passwordConfirmation },
setState
] = useState(initialState);
const clearState = () => {
setState({ ...initialState });
};
const onChange = e => {
const { name, value } = e.target;
setState(prevState => ({ ...prevState, [name]: value }));
};
const handleSubmit = e => {
e.preventDefault();
signupUser().then(clearState);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Username:
<input value={username} name="username" onChange={onChange} />
</label>
</div>
<div>
<label>
Email:
<input value={email} name="email" onChange={onChange} />
</label>
</div>
<div>
<label>
Password:
<input
value={password}
name="password"
type="password"
onChange={onChange}
/>
</label>
</div>
<div>
<label>
Confirm Password:
<input
value={passwordConfirmation}
name="passwordConfirmation"
type="password"
onChange={onChange}
/>
</label>
</div>
<button>Submit</button>
</form>
);
};
ReactDOM.render(<Signup />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
答案 1 :(得分:4)
我认为投票的答案仍然正确,但是最近React发布了新的内置useReducer
,以他们自己的话来说就是
方便以后在响应动作时重置状态
https://reactjs.org/docs/hooks-reference.html#usereducer
它还指出,当您具有涉及多个子值的复杂状态逻辑时,或者当下一个状态依赖于前一个值时,通常最好使用useState。
在投票答案上使用相同的示例,您可以像这样使用useReducer:
import React, { useReducer } from "react";
const initialState = {
username: "",
email: "",
password: "",
passwordConfirmation: "",
};
const reducer = (state, action) => {
if (action.type === "reset") {
return initialState;
}
const result = { ...state };
result[action.type] = action.value;
return result;
};
const Signup = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const { username, email, password, passwordConfirmation } = state;
const handleSubmit = e => {
e.preventDefault();
/* fetch api */
/* clear state */
dispatch({ type: "reset" });
};
const onChange = e => {
const { name, value } = e.target;
dispatch({ type: name, value });
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Username:
<input value={username} name="username" onChange={onChange} />
</label>
</div>
<div>
<label>
Email:
<input value={email} name="email" onChange={onChange} />
</label>
</div>
<div>
<label>
Password:
<input
value={password}
name="password"
type="password"
onChange={onChange}
/>
</label>
</div>
<div>
<label>
Confirm Password:
<input
value={passwordConfirmation}
name="passwordConfirmation"
type="password"
onChange={onChange}
/>
</label>
</div>
<button>Submit</button>
</form>
);
};
export default Signup;
import React, { FC, Reducer, useReducer } from "react";
interface IState {
email: string;
password: string;
passwordConfirmation: string;
username: string;
}
interface IAction {
type: string;
value?: string;
}
const initialState: IState = {
email: "",
password: "",
passwordConfirmation: "",
username: "",
};
const reducer = (state: IState, action: IAction) => {
if (action.type === "reset") {
return initialState;
}
const result: IState = { ...state };
result[action.type] = action.value;
return result;
};
export const Signup: FC = props => {
const [state, dispatch] = useReducer<Reducer<IState, IAction>, IState>(reducer, initialState, () => initialState);
const { username, email, password, passwordConfirmation } = state;
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
/* fetch api */
/* clear state */
dispatch({ type: "reset" });
};
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
dispatch({ type: name, value });
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Username:
<input value={username} name="username" onChange={onChange} />
</label>
</div>
<div>
<label>
Email:
<input value={email} name="email" onChange={onChange} />
</label>
</div>
<div>
<label>
Password:
<input
value={password}
name="password"
type="password"
onChange={onChange}
/>
</label>
</div>
<div>
<label>
Confirm Password:
<input
value={passwordConfirmation}
name="passwordConfirmation"
type="password"
onChange={onChange}
/>
</label>
</div>
<button>Submit</button>
</form>
);
};
请注意,我将此reducer
函数const创建为尽可能通用,但是您可以完全更改它并测试不同的操作类型(除了简单的状态属性名称)并在返回修改后的状态之前执行复杂的计算。上面提供的链接中有一些示例。
答案 2 :(得分:4)
如果您想要一种快速的n'n肮脏方法,您可以尝试仅更改组件的键,这将导致React卸载您的旧组件实例并安装一个新的实例。
我在这里使用Lodash来生成唯一的一次性ID,但假设所需的时间分辨率在1毫秒以上,那么您也可以放弃public static Action<TimeSpan, CancellationToken> Sleep = (timeSpan, cancellationToken) =>
{
if (cancellationToken.WaitHandle.WaitOne(timeSpan))
cancellationToken.ThrowIfCancellationRequested();
};
或类似的东西。
我第二次以Date.now()
的身份传递密钥,以便更轻松地了解发生了什么,但这不是必需的。
debugKey
const StatefulComponent = ({ doReset, debugKey }) => {
const [counter, setCounter] = React.useState(0);
const increment = () => setCounter(prev => prev + 1);
return (
<React.Fragment>
<p>{`Counter: ${counter}`}</p>
<p>{`key=${debugKey}`}</p>
<button onClick={increment}>Increment counter</button>
<button onClick={doReset}>Reset component</button>
</React.Fragment>
);
};
const generateUniqueKey = () => `child_${_.uniqueId()}`;
const App = () => {
const [childKey, setChildKey] = React.useState(generateUniqueKey());
const doReset = () => setChildKey(generateUniqueKey());
return (
<div className="App">
<StatefulComponent key={childKey} debugKey={childKey} doReset={doReset} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
答案 3 :(得分:2)
据我所知(通过阅读react docs)-目前尚无办法。
答案 4 :(得分:2)
您本可以在钩子中使用useRef
const myForm = useRef(null)
const submit = () => {
myForm.current.reset(); // will reset the entire form :)
}
<form ref={myForm} onSubmit={submit}>
<input type="text" name="name" placeholder="John Doe">
<input type="email" name="name" placeholder="usman@gmail.com">
<button type="submit">Submit</button>
</form>
答案 5 :(得分:2)
我刚刚编写了一个返回实际钩子的自定义钩子,以及一个 resetState
函数。
用法:
const [{
foo: [foo, setFoo],
bar: [bar, setBar],
},
resetState,
] = useStateWithReset({
foo: null,
bar: [],
})
// - OR -
const [
[foo, setFoo],
[bar, setBar],
],
resetState,
] = useStateWithReset([
null,
[],
])
后者可读性较差,但前者会复制密钥,因此没有完美的解决方案。
代码:
const useStateWithReset = initialState => {
const hooksArray = Object.fromEntries(
Object.entries(initialState).map(([k, v]) => {
return [k, useState(v)]
})
);
const resetState = () =>
Object.entries(initialState).map(
([k, v]) => hooksArray[k][1](v)
);
return [hooksArray, resetState];
};
答案 6 :(得分:1)
您可以按照FAQ中的说明使用一个状态变量:https://reactjs.org/docs/hooks-faq.html#should-i-use-one-or-many-state-variables
这当然取决于您的用例。
从父容器中重命名组件当然也会自动将其重置。
答案 7 :(得分:1)
除了其他答案,我建议您选择一个帮助程序库like this,或者如果需要经常做的话,可以在钩子上进行自己的抽象。
useState
和朋友实际上只是低级原语,对于您(用户)而言,它可以在其上构建更多有用的钩子。我有一些项目,其中原始useState
调用实际上很少见。
答案 8 :(得分:1)
这有一个非常简单的解决方案。您可以在渲染组件的位置更改关键道具。 例如,如果我们有要编辑的组件,则可以传递另一个键来清除以前的状态。
return <Component key={<different key>} />
答案 9 :(得分:0)
我完全同意@Tholle的回答。
如果在清除状态后需要运行某些功能
String line = "2019 May 22 03:32:17.952296 france1v4 sh[4937]: 190522-03:32:17.951792 [mod=REC, lvl=INFO] [tid=26130] Recording A8602096210405800406L200218680503121519 size is 4145956224 bytes";
String pattern = "^.+\\.(\\d+)";
// Create a Pattern object
Pattern r = Pattern.compile(pattern);
// Now create matcher object.
Matcher m = r.matcher(line);
if (m.find( )) {
System.out.println("Found value: " + m.group(1) ); //This would give 951792
}else {
System.out.println("NO MATCH");
}
答案 10 :(得分:0)
我有一个类似的用例。 Completelty与登录,注册机制无关,但我将其更改为与您的用例有关。
解决此问题的一种简单方法是在我看来使用父组件。
const initUser = {
name: '',
email: '',
password: '',
passwordConfirmation: ''
}
const LoginManager = () => {
const [user, setUser] = useState(initUser)
return <Signup user={user} resetUser={setUser} />
}
const Signup = ({user, resetUser}) => {
const [username, setUsername] = useState(user.name)
const [email, setEmail] = useState(user.email)
const [password, setPassword] = useState(user.password)
const [passwordConfirmation, setPasswordConfirmation] = useState(user.passwordConfirmation)
const handleSubmit = signupUser => e => {
e.preventDefault()
signupUser().then(data => {
console.log(data)
resetUser(initUser) // <-----------
})
}
return <JSX />
}
export default Signup
答案 11 :(得分:-1)
提交表单后,您可以通过这种方法在钩子中重置输入值(来自对象)。
您可以在同一useState
中定义多个输入值,例如名字,姓氏,等 ...
const [state, setState] = React.useState({ firstName: "", lastName: "" });
示例代码。
export default function App() {
const [state, setState] = React.useState({ firstName: "", lastName: "" });
const handleSubmit = e => {
e.preventDefault();
setState({firstName:'',lastName:''})
};
const handleChange = e => {
const { name, value } = e.target;
setState({ ...state, [name]: value });
};
console.log(state)
return (
<form onSubmit={handleSubmit}>
<input
type="text"
name="firstName"
placeholder="Enter first name"
value={state.firstName}
onChange={handleChange}
/>
<input
type="text"
name="lastName"
placeholder="Enter last name"
value={state.lastName}
onChange={handleChange}
/>
<input type="submit" value="Submit" />
</form>
);
}
如果要在对象中定义多个输入而不是单独声明。