Problem setting state via function triggered from child component

Hello,

I’m trying to move data between sibling components, without redux just with toggled function that brings data from child component (Cards). at this point everything is cool I can do console.log for data and it shows well.

Parent component :

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import Header from './components/header';
import Cards from './components/cards';
import Footer from './components/footer';
class App extends Component {
  state = {
    to_favorite: [],
  };
  toFav = data => {
    this.setState(function(prevState, props) {
      if (prevState.to_favorite !== data) {
      if (prevState.to_favorite.includes(data) === false) {
        return {to_favorite: data};
      }
      }
    });
  };
  render() {
    return (
      <React.Fragment>
        <Header data={this.state.to_favorite} />
        <div className="cards-body">
          <Cards toFav={this.toFav} />
        </div>
        <Footer />
      </React.Fragment>
    );
  }
}

export default App;

child component which include the triggerd function isaFav() :

import React, {Component} from 'react';
import Card from './card';

class Cards extends Component {
  state = {
    books: [
      {
        id: '1',
        title: 'HTTP: The Definitive Guide',
        author: 'David Gourley',
        cover: 'http',
        price: '46,61',
      },
      {
        id: '2',
        title: 'HTTP: The Definitive Guide',
        author: 'David Flanagan',
        cover: 'js',
        price: '35,52',
      },
      {
        id: '3',
        title:
          'The TCP/IP Guide: A Comprehensive, Illustrated Internet Protocols Reference',
        author: 'Charles M.Kozierok',
        cover: 'tcp_ip',
        price: '54,50',
      },
      {
        id: '4',
        title:
          'Node.js 8 the Right Way: Practical, Server-Side JavaSCript The Scales',
        author: 'Jim Wilson',
        cover: 'nodejs',
        price: '28,21',
      },
    ],
    favorite: [],
    bag: [],
  };

  isaFav = data => {
    if (typeof data === 'object') {
      this.setState({favorite: [...this.state.favorite, data]});
    } else {
      this.setState({
        favorite: this.state.favorite.filter(fav => fav.id != data[0]),
      });
    }
  };
  render() {
    return (
      <div className="cards" tofav={this.props.toFav(this.state.favorite)}>
        {this.state.books.map(book => (
          <Card isaFav={this.isaFav} bookInfos={book} />
        ))}
      </div>
    );
  }
}

export default Cards;

the problem comes when I try to set state to the parent component that include the toggled function, that function is triggering many times. at the end it shows me this error.

react-dom.development.js:55 Uncaught Invariant Violation: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

componentDidMount can’t stop that function from triggering ,

is there any solution for that? and is it the appropriate way to work with states in react? I will appreciate your help :slight_smile:

My first guess would be that the problem is here:

<div ... tofav={this.props.toFav(this.state.favorite)}>

What is the purpose of tofav?

to move data to the parent component app.js

Can you explain me how you think it works?

btw, I’m a newbie with react.
what I wan’t to do is moving data from child components (card > cards> app) to the parent (app) then when I set that date a state to app component I will use it as a props to header component.

Use codesandbox.io to host your code. It will be easier to just show.

something went wrong with importing the repo to codesandbox. Please you can check the repo on GitHub
yassinemellouki/GeekBook

Add node_modules to .gitignore and try again.