Jonathan Toledo
Jonathan Toledo

Reputation: 359

clear an array before populate with useState in react

How to clear an array and immediately populate with react using hooks (useState)

const [log, setLog] = useState([]);

const onSubmit = data => {
  let num = parseInt(data.num);
  setLog([]);
  for (let i = 1; i <= num; i++) {
    axios
      .get(data.url)
      .then(function(response) {
        setLog([...log, { type: "ok", message: "Good" }]);
      })
      .catch(function(error) {
        setLog([...log, { type: "error", message: "Bad" }]);
      });
  }
};

In this code, setLog([]) fails to clean the array because is asynchronous. How can I handle this? Thanks in advance.

Edit: I am creating a request log to a URL and save the request result. It can be 1 attempt or many attempts and I must record all the responses. Each time I press the submit button, the log must be cleaned and the requests started again.

Upvotes: 1

Views: 4277

Answers (3)

Amin Azimi
Amin Azimi

Reputation: 749

I think this will work:

const [log, setLog] = useState([]);

const onSubmit = data => {
  let num = parseInt(data.num);

  for (let i = 1; i <= num; i++) {
    axios
      .get(data.url)
      .then(function(response) {
        setLog([{ type: "ok", message: "Good" }]);
      })
      .catch(function(error) {
        setLog([{ type: "error", message: "Bad" }]);
      });
  }
};

Upvotes: 0

Alan Darmasaputra
Alan Darmasaputra

Reputation: 468

Unpopular opinion:

Use class component. It provides accessor to the current state.

class SomeComponent extends Component {
  state = {
    isSubmitting: false,
    logs: []
  }

  async submit(data){
    const num = data.num;
    if (this.isSubmitting) {
      return;
    }

    let logs = [];
    this.setState({ logs, isSubmitting: true });

    for (const i = 0; i < num; i++) {
      await axios.get(data.url)
        .then(() => {
          logs = logs.concat({ type: "ok", message: "Good" });
          this.setState({ logs });
        })
        .catch(() => {
          logs = logs.concat({ type: "error", message: "Bad" })
          this.setState({ logs })
        })
    }

    this.setState({ isSubmitting: false });
  }

  render(){
    return (
      <form onSubmit={() => this.submit(getSomeData())}></form>
    )
  }
}


// use this if you want the request to be executed parallely

  async submit(data){
    const num = data.num;
    if (this.isSubmitting) {
      return;
    }

    let logs = [];
    this.setState({ logs, isSubmitting: true });

    const requests = []
    for (const i = 0; i < num; i++) {
      requests.push(
        axios.get(data.url)
          .then(() => {
            logs = logs.concat({ type: "ok", message: "Good" });
            this.setState({ logs });
          })
          .catch(() => {
            logs = logs.concat({ type: "error", message: "Bad" })
            this.setState({ logs })
          })
      )
    }

    await Promise.all(requests)

    this.setState({ isSubmitting: false });
  }

Upvotes: 1

rMonteiro
rMonteiro

Reputation: 1696

why do you want to do setLog([]) and then setLog([...log, ]); ?

If you want to setLog without previous log content just do:

const [log, setLog] = useState([]);

const onSubmit = data => {
  let num = parseInt(data.num);
  for (let i = 1; i <= num; i++) {
    axios
      .get(data.url)
      .then(function(response) {
        setLog([{ type: "ok", message: "Good" }]);
      })
      .catch(function(error) {
        setLog([{ type: "error", message: "Bad" }]);
      });
  }
};

edit: Ok I think I understood what you need. I am not sure but try the following

const [log, setLog] = useState([]);

const onSubmit = data => {
  let num = parseInt(data.num);
  setLog([]);
  for (let i = 1; i <= num; i++) {
    axios
      .get(data.url)
      .then(function(response) {
        setState(prevLog => {
          prevLog.push({ type: "ok", message: "Good" });
          return {prevLog};
        });
      })
      .catch(function(error) {
        setState(prevLog => {
          prevLog.push({ type: "error", message: "Bad" });
          return {prevLog};
        });
      });
  }
};

Upvotes: 1

Related Questions