0

The problem is the following:

when I receive props from parent component with the data of a new element, A new card must be added, but instead of it, the code starts to add this card an infinite number of times.

How to fix this? Code is below

const fetchCards = () => {
  return Axios(apiOptions('GET')).then(
    response => response.data,
    error => {
      console.log(`[Error]: ${error}`);
    }
  );
};
const addCard = props => {
  return Axios(apiOptions('POST', props))
    .then(result => result.data)
    .catch(error => console.log(error));
};
const PlacesList = props => {
  const [cards, setCards] = useState([]);

  useEffect(() => {
    fetchCards().then(res => setCards(res))
  }, []);

// Problem with this part 

  if (props.newCard.titleValue !== undefined) {
      console.log(props.newCard.titleValue);
      addCard(props.newCard).then(res => setCards(cards.concat(res)));
    }


const createCards = () => {
    return cards
      .map((card, id) => {
        if (id > cards.length - 10) {
          return (
            <PlaceCard
              title={card.name}
              url={card.link}
            />
          );
        }
        return false;
      })
      .reverse();
  };

  return <div className="places-list root__section">{createCards()}</div>;
};
export default PlacesList;

Simplified example Codesandbox

3
  • sandbox, please. Commented Jan 26, 2020 at 15:14
  • @PiotrŻak added Commented Jan 27, 2020 at 7:29
  • Ok - i slept - but you see, automatically another person solve your ticket Commented Jan 27, 2020 at 10:54

1 Answer 1

1

NOTE: The answer below are based on the codesandbox you gave and not the snippet you provided:

To answer what causes the issue is:

    if (props.newItem) {
      setItems(items.concat([10]));
    }

this code chunk is being rendered on the component root and not inside of any useEffect or callback function. Every "render" of the component will call the setItems and since any state change (these are triggered by setState or the second result on useState) will cause a re-render on the component, what will happen is it will re-render infinitely.


To answer your problem:

on your List component, add this:


  useEffect(() => {
    if (props.newItem) {
      setItems(items.concat([10]));
    }
  }, [props.newItem]);`

This will only take effect if the value of props.newItem was updated.

But this is will not work when you click the button again since the value of newItems is always true.

To fix that, add setNewItem when calling List (i.e):

<List newItem={newItem} setNewItem={setNewItem} />

This will pass give your List component the ability to change the item value. so let's add this to your useEffect on the second code chunk above like:

  useEffect(() => {
    if (props.newItem) {
      setItems(items.concat([10]));
      props.setNewItem(false);
    }
  }, [props.newItem]);`

we set it to false so it will always toggle the value of newItem and will always add a new item on your list.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.