0

I am really new to React JS. I am making a small project that has a table with movies in it. In the top it shows how many movies are there.

My problem is that this.setState() is not working. It is showing an error numberOfMovies is not defined.

My Code -

import React, { Component } from "react";
import "../services/fakeMovieService";

export const movies = [
    {
        _id: "5b21ca3eeb7f6fbccd471815",
        title: "Terminator",
        genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
        numberInStock: 6,
        dailyRentalRate: 2.5,
        publishDate: "2018-01-03T19:04:28.809Z",
    },
    {
        _id: "5b21ca3eeb7f6fbccd471816",
        title: "Die Hard",
        genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
        numberInStock: 5,
        dailyRentalRate: 2.5,
    },
    {
        _id: "5b21ca3eeb7f6fbccd471817",
        title: "Get Out",
        genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
        numberInStock: 8,
        dailyRentalRate: 3.5,
    },
    {
        _id: "5b21ca3eeb7f6fbccd471819",
        title: "Trip to Italy",
        genre: { _id: "5b21ca3eeb7f6fbccd471814", name: "Comedy" },
        numberInStock: 7,
        dailyRentalRate: 3.5,
    },
    {
        _id: "5b21ca3eeb7f6fbccd47181a",
        title: "Airplane",
        genre: { _id: "5b21ca3eeb7f6fbccd471814", name: "Comedy" },
        numberInStock: 7,
        dailyRentalRate: 3.5,
    },
    {
        _id: "5b21ca3eeb7f6fbccd47181b",
        title: "Wedding Crashers",
        genre: { _id: "5b21ca3eeb7f6fbccd471814", name: "Comedy" },
        numberInStock: 7,
        dailyRentalRate: 3.5,
    },
    {
        _id: "5b21ca3eeb7f6fbccd47181e",
        title: "Gone Girl",
        genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
        numberInStock: 7,
        dailyRentalRate: 4.5,
    },
    {
        _id: "5b21ca3eeb7f6fbccd47181f",
        title: "The Sixth Sense",
        genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
        numberInStock: 4,
        dailyRentalRate: 3.5,
    },
    {
        _id: "5b21ca3eeb7f6fbccd471821",
        title: "The Avengers",
        genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
        numberInStock: 7,
        dailyRentalRate: 3.5,
    },
];

export class Table extends Component {
    state = {
        numsOfMovies: 0,
    };

    tableRender = () => {
        this.setState({ numsOfMovies: numsOfMovies + 1 });
        return movies.map((elem) => (
            <tr key={elem._id}>
                <td className="title">{elem.title}</td>
                <td>{elem.dailyRentalRate}</td>
                <td>{elem.genre.name}</td>
                <td>
                    <button>Delete</button>
                </td>

                {console.log(elem._id)}
            </tr>
        ));
    };
    render() {
        return (
            <>
                {this.state.numsOfMovies === 0 ? (
                    <h1>There are currently no movies from database.</h1>
                ) : (
                    <h1>
                        There are currently {this.state.numsOfMovies} movies
                        fromthe database."
                    </h1>
                )}
                <table>
                    <thead>
                        <tr>
                            <td>Name</td>
                            <td>Rate</td>
                            <td>Genre</td>
                            <td>Button</td>
                        </tr>
                    </thead>

                    <tbody>{this.tableRender()}</tbody>
                </table>
            </>
        );
    }
}

export default Table;

I have coded it so that it increases the state count every times it renders a table row using the map method. But it doesn't work even though I am using arrow functions. The error is - src/components/Table.jsx Line 77:39: 'numsOfMovies' is not defined no-undef

How to prevent this error?? IT SHOULD BE A CLASS COMPONENT

Thanks in advance.

6
  • You just need to reference the state object key instead of trying to access a local variable. this.setState({ numsOfMovies: this.state.numsOfMovies + 1 });. Obviously there are other ways including a functional update, but this will work in most cases. Commented Jun 14, 2021 at 17:56
  • @BrianThompson I tried that, then this error is coming - × Error: 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. Commented Jun 14, 2021 at 17:58
  • Yeah, you're calling this function in the render method, and the function makes a state update which triggers a re-render and --- infinite loop. You need to limit when you're calling the function. Commented Jun 14, 2021 at 18:00
  • @BrianThompson Okay I understood that. So, preventing it is not possible? Commented Jun 14, 2021 at 18:02
  • Preventing it is possible, it will just require you to restructure your code slightly to only update state as you need to and not every single render. Commented Jun 14, 2021 at 18:03

1 Answer 1

2

Try updating your setState function to the following. It is an updater function that provides the current state value. This is useful incrementing or similar as you are wanting to increment the current value in state:

this.setState((state) => ({ numsOfMovies: state.numsOfMovies + 1 }));

Regarding your other issue, you are executing a setState inside a render via tableRender() which is causing a new render endlessly. It sounds like you are wanting to calculate numOfMovies. Instead of trying to execute setState inside the map/loop, try just using something like movies.length and update the state once which will avoid many extra re-renders.

Hopefully that helps!

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

5 Comments

Thanks I tried that, but then this error is coming - Error: 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.
I update the answer but it's because you are executing setState inside of render via tableRender(). You need to move any setState outside of rendering such as componentDidMount or an event handler. Basically it endlessly updates state incrementing the value. Also from business logic perspective why would you want to increment the numOfMovies randomly? Did you intend to increment when a specific action happens like a movie is added or data from HTTP request is completed?
Yeah , I wanted it to happen when a movie data is added using the movies.map() method.
Why not just use movies.length or similar given you know how many movies exist rather than executing a setState() inside a loop, which you also do NOT want do usually. You can avoid many re-renders by updating the state once right?
Ohhh Okay Thanks.

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.