Search code examples
reactjsformsreact-state-management

Prevent form from resetting inputs states in ReactJs


After submitting a login form, am getting my errors from the Api for every specific case and displaying them under the right inputs. The problem is whether the login succeeded or not after submitting, the input states are getting initialised, the errors are displaying but for the every time the user must returns to all the inputs and refill them again and again which is very annoying.

I am a beginner with react, and am really stuck with this issues. Here is where am i now.

Snippet on my login class :

class Login extends Component {
constructor(props) {
super(props);
this.state = {
  email: "",
  password: "",
  isLoggedIn: false,
  user: {}
 };
 this.onChange = this.onChange.bind(this);
 this.login = this.login.bind(this);
}

login(e) {
 e.preventDefault();
 this.props.login(this.state.email, this.state.password);
 }

onChange(e) {
this.setState({ [e.target.name]: e.target.value });
}

Example of my input :

 <div className="form-group centerErrs">
                      <input
                        type="text"
                        value={this.state.email}
                        onChange={this.onChange}
                        className="form-control form-control-user"
                        placeholder="Username or Email Address"
                        autoComplete="off"
                        id="email-input"
                        name="email"
                      />
                      {this.props.errors ? (
                        <small className="form-text  red">
                          {this.props.errors.email}
                        </small>
                      ) : null}
                    </div>

Snippet of my login function :

 var formData = new FormData();
 formData.append("email", email);
 formData.append("password", password);

   //posting to the api 
  .then(json => {
    if (json.data.success) {
      //handling the user data

      let appState = {
        isLoggedIn: true,
        user: userData
      };
      // save app state with user date in local storage
      localStorage["appState"] = JSON.stringify(appState);
      this.setState({
        isLoggedIn: appState.isLoggedIn,
        user: appState.user
      });

      //updated : here how i handle in fail case
      else {
      let appState = {
        isLoggedIn: false,
        errors: json.data
      };
      this.setState({
        isLoggedIn: appState.isLoggedIn,
        errors: appState.errors
      });
    }

Update : this is my parent component constructor :

    constructor(props) {
    super(props);
    this.state = {
    isLoggedIn: false,
    user: {},
    errors: {},
    };
   this.login = this.login.bind(this);
  }

Update the login container :

   const LoginContainer = () => (
   <div>
    {!this.state.isLoggedIn ? (
      <Login login={this.login} errors={this.state.errors} />
    ) : (
      <Redirect to="/" />
    )}
   </div>
 );

And the render in the parent :

 <Route exact path="/(login)" component={LoginContainer} />

What i just want is to keep the inputs state if the form submission fails.

I will appreciate any kind of help and thank you in advance.


Solution

  • As long as the LoginContainer is a function, not a ReactJs Component it will recreate the whole UI so you should convert it to React.Component and the logic of checking Auth status should not be inside the LoginContainer because the route Login shouldn't exist if the user is loggedin

    {this.state.loggedin?
     [Auth routes]:
     [<Route exact path="/(login)" component={LoginContainer} />...]
    

    P.S. it is preferable to use a global store to store the auth state like redux or unstated or any others.