Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reset to Initial State with React Hooks

I'm currently working on a signup form and the following is a snippet of my code:

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 

Each piece of state is used for a controlled input for the form.

Essentially what I want to do is after the user has successfully signed up, I want the state to go back to the initial state with the fields cleared.

It's quite imperative to manually set each piece of state back to empty strings inclearState I was wondering if there is a method or function that comes with React that resets the state back to its initial values?

like image 273
avatarhzh Avatar asked Feb 26 '19 23:02

avatarhzh


People also ask

How do you initialize a state in React hooks?

If you want to set initial state after loading data (fetch data from api) you can use "useEffect" in React hooks. it is equal to "componentWillReceiveProps" in class component. so when you set state value in useEffect make sure avoid infinity loop eg ..

Can you initialize state from a function in React hooks?

With React 16.8, function components can now use state. Before this, data from the state had to be passed down as props from class components to function components or you had to convert your function component to a class component. Now, we can use React hooks, and to use state we can use the useState hook.

How do you clear the state in React?

state = initialState; requires you never to mutate your state, otherwise you'll pollute initialState and make a reset impossible. If you can't avoid mutations, then you'll need to create a copy of initialState in the constructor. (Or make initialState a function, as per getInitialState() .)


2 Answers

There is no built-in way to set the state to its initial value, sadly.

Your code looks good, but if you want to decrease the functions needed you can put your entire form state in a single state variable object and reset to the initial object.

Example

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>
like image 136
Tholle Avatar answered Sep 28 '22 03:09

Tholle


I think the voted answer is still correct, but recently React released the new built-in useReducer which, in their own words, is

handy for resetting the state later in response to an action

https://reactjs.org/docs/hooks-reference.html#usereducer

Also it states that it's usually preferable useReducer when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.

Using the same sample on the voted answer, you could use useReducer like this:

Javascript

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; 

Typescript

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

Notice that I created this reducer function const to be as generic as possible, but you can completely change it and test different action types (other than simply state property names) and perform complex calculations before returning the state modified. There are some examples in the link provided above.

like image 45
Guilherme Avatar answered Sep 28 '22 05:09

Guilherme