简体   繁体   中英

SetState using the foreach loop does not work

I am trying to update the state using the following code:

handleCheckBox = () => {
    this.setState(({isCheckd}) => ({isCheckd: !isCheckd, isEnable: !isCheckd}), () => 
      this.props.untracked.forEach((item) => this.setState({ [item.resumeId]: this.state.isCheckd })),
      this.props.tracked.forEach((item) => this.setState({ [item.resumeId]: this.state.isCheckd }))
    );
  }

When I try to update using the forEach function. In the first loop the state gets updated as you see the conditons are the same. but in this first one gets change but second for each does not get change. If I change the order in which they are written then the whichever is first it's state gets changed but not the second one.

handleTableCheckboxChange = (e, type) => {
    this.setState({
      [e.target.name]: e.target.checked
    }, () => {
      const checkedItems = this.props[type].filter((item) => this.state[item.resumeId])
      this.setState({
        isCheckd: checkedItems.length === this.props[type].length ? true : false,
        isEnable: checkedItems.length > 1 ? true : false
      });
    });
  }

How can I prevent this from happening?

As I said in comments on your previous question, you're breaking one of the fundamental rules of React : If you're setting state based on existing state , you must use the callback version of setState , not the version you pass an object into.

Looking at that code, doing so would look something like this:

handleCheckBox = () => {
  this.setState(
    ({isCheckd}) => ({isCheckd: !isCheckd, isEnable: !isCheckd}),
    () => this.setState(({isCheckd}) => {
      const newState = {};
      for (const item of [...this.props.untracked, ...this.props.tracked]) {
        newState[item.resumeId] = isCheckd;
      }
      return newState;
    })
  );
}

But , a couple of odd things jump out:

  1. It's not clear why you're calling setState again in the completion handler of the outer setState .

  2. It's not clear why you have tracked and untracked when you're doing the same thing with them.

If you can do it in one state update, that would probably be better:

handleCheckBox = () => {
  this.setState(({isCheckd}) => {
    const newState = {
      isCheckd: !isCheckd,
      isEnable: !isCheckd
    };
    for (const item of [...this.props.untracked, ...this.props.tracked]) {
      newState[item.resumeId] = isCheckd;
    }
    return newState;
  });
}

Re your updated question, handleTableCheckboxChange has the same problem (setting state based on existing state passing an object into setState ) and thus the same solution (use the callback version) applies:

handleTableCheckboxChange = ({target: {name, checked}}, type) => {
  this.setState(prevState => {
    const newState = {[name]: checked};
    const checkedItems = this.props[type].filter((item) => prevState[item.resumeId]);
    newState.isCheckd = checkedItems.length === this.props[type].length;
    newState.isEnable = checkedItems.length > 1;
    return newState;
  });
};

(Notice I've removed the ? true : false from the lines setting isCheckd and isEnable . === and > already give you a boolean, there's no point served by adding a conditional operator there.)

Hey I'm facing same problem recently.but I got the solution.

const [data,setData] = useState([]);
const emails = ["127","hello1","here"];
emails.forEach((email)=>{
   setData((prev) => [...prev,emial])
 })

Above code gives me an error

Too many re-renders. React limits the number of renders to prevent an infinite loop.

Solution

const [data,setData] = useState([]);
const emails = ["127","hello1","here"];
useEffect(()=>{
 emails.forEach((email)=>{
   setData((prev) => [...prev,emial])
 })
 },[])

Put forEach or map inside useEffect for avoiding the error and state will also update

May be this answer helps some who facing same error

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM