Home > Back-end >  Reset/Set state on a button onClick
Reset/Set state on a button onClick

Time:11-28

I have a custom form with at least two different types of Components: One for a textfield, and another for a number, and when I click the "Submit" button (itself just a button, not wrapped in a form) I want to set the state of the fields back to 0/Empty. I'm not really clear here on how to restore these to their defaults. I know that I need to pass setState() at some point since I can't "zero out" like with traditional Javascript, but I am confused since the click operation would never reference the components. What am I missing here?

import './App.css';
import React from 'react';

class NumberField extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: 0 };
  }

  changeHandler = event => {
    event.persist();

    let value = event.target.value;

    this.setState(prevState => ({
      item: { ...prevState.value, [event.target.value]: value }
    }))
  };

  render() {
    return (
      <div>
        <label for={this.props.label}>{this.props.labelName}</label>
        <button onClick={this.decrement}>-</button>
        <input type="number" 
          name={this.props.label} 
          id={this.props.label} 
          value={this.state.value}
          onChange={this.changeHandler}>
        </input>
        <button onClick={this.increment}> </button>
      </div>
    );
  }
}

class TextField extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: "" };
  }

  render() {
    return (
      <div>
        <label for={this.props.label}>{this.props.labelName}</label>
        <input type="text" name={this.props.label} id={this.props.label} placeholder={this.props.placeholder}></input>
      </div>
    );
  }
}

function handleSubmit(e) {
  e.preventDefault();
  console.log("Form Submitted");
  // TODO Reset the state on all components so everything goes back to 0/Empty somehow
}

function App() {
  return (
    <div className="App">
      <div className="AppForm">
        <TextField labelName="Ferry Name" label="ferry_name" placeholder="Enter the ferry name" />

        <div>
          <NumberField labelName="Number of seats" label="seats" />
        </div>
      <div className="formSubmit">
        <button onClick={handleSubmit}>Book Ferry</button>
      </div>
      </div>
    </div>
  );
}

export default App;

CodePudding user response:

Note: If you want to access component's state inside a function, then you must declare that function inside the component.


Other than that, what you want to do can't be directly achievable by how you are handling child component's state.

If you want to change the child component's state, the due to unidirectional nature of react, you can't simply access the child's state.

  1. What you can do is, you can have a state = {number:0, text: ""} in App Component and pass update Functions and field values as props to the Child Components

  2. Another way (not recommended in react doc), if don't want to keep your state in Parent is, using useImperativeHandle. You can read about it in Link to doc

  3. One more way (recommended for larger projects), is to use global state managements like redux, context, etc.

CodePudding user response:

As you mentioned you should send two more props, I named them reset and changed and also I changed your class components to functional

const {useEffect,useState} = React;

const NumberField = (props) => {
  const [value, setValue] = useState(0);
  useEffect(() => {
    if (props.reset) setValue(0);
  }, [props.reset]);

  const increment = () => {
    setValue((value) => value   1);
  };
  const decrement = () => {
    setValue((value) => value - 1);
  };

  const changeHandler = (event) => {
    event.persist();
    props.changed();
    setValue(event.target.value);
    //let value = event.target.value;

    //setValue(prevState => ({
    //  item: { ...prevState.value, [event.target.value]: value //}
    //}))
  };
  return (
    <div>
      <label for={props.label}>{props.labelName}</label>
      <button onClick={decrement}>-</button>
      <input
        type="number"
        name={props.label}
        id={props.label}
        value={value}
        onChange={changeHandler}
      ></input>
      <button onClick={increment}> </button>
    </div>
  );
};


const TextField = (props) => {
  const [value, setValue] = useState("");
  useEffect(() => {
    if (props.reset) setValue("");
  }, [props.reset]);
  const handleChange = (event) => {
    setValue(event.target.value);
    props.changed();
  };
  return (
    <div>
      <label for={props.label}>{props.labelName}</label>
      <input
        value={value}
        onChange={handleChange}
        type="text"
        name={props.label}
        id={props.label}
        placeholder={props.placeholder}
      ></input>
    </div>
  );
};

const App=()=> {
const [reset, setReset] = useState();
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log("Form Submitted");
    setReset(true);
    // TODO Reset the state on all components so everything goes back to 0/Empty somehow
  };
  const handleChanged = () => {
    setReset(false);
  };
  return (
    <div className="App">
      <div className="AppForm">
        <TextField
          reset={reset}
          changed={handleChanged}
          labelName="Ferry Name"
          label="ferry_name"
          placeholder="Enter the ferry name"
        />

        <div>
          <NumberField
            reset={reset}
            changed={handleChanged}
            labelName="Number of seats"
            label="seats"
          />
        </div>
        <div className="formSubmit">
          <button onClick={handleSubmit}>Book Ferry</button>
        </div>
      </div>
    </div>
  );
}
ReactDOM.render( <App/> ,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related