skip to Main Content

New to learning class components in React. I have two very simple components, App.tsx and card-list.component.tsx. App.tsx fetches a list of random users (called monsters in the code haha). It also renders a search box and card-list.component.tsx. All it does is provide the ability to filter the list when something is typed in the search bar. Here are the files:

App.tsx:

import { ChangeEvent, Component } from "react";
import "./App.css";
import CardList from "./components/card-list/card-list.component";

export interface Monster {
  id: number;
  name: string;
  username: string;
  email: string;
  address: {
    street: string;
    suite: string;
    city: string;
    zipcode: string;
    geo: {
      lat: string;
      lng: string;
    };
  };
  phone: string;
  website: string;
  company: {
    name: string;
    catchPhrase: string;
    bs: string;
  };
}

interface State {
  monsters: Monster[];
  searchedString: string;
  errorMessage: string;
}

class App extends Component<any, State> {
  constructor(props: any) {
    super(props);
    //console.log("construcor");
    this.state = {
      monsters: [],
      searchedString: "",
      errorMessage: "",
    };
  }

  componentDidMount() {
    // console.log("componentDidMount");
    // componentDidMount is called immediately after a React component has been rendered to the screen (mounted).
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((response) => response.json())
      .then((users) => {
        this.setState({ monsters: users });
      })

      .catch((error) => {
        // Handle the error here
        // console.error("Error fetching data:", error);
        // You can update the state with an error message to display it in the UI
        this.setState({
          errorMessage: "Error fetching data. Please try again later.",
        });
      });
  }

  onSearch = (event: ChangeEvent<HTMLInputElement>) => {
    this.setState({
      ...this.state,
      searchedString: event.target.value,
    });
  };

  render() {
    const { monsters: monstersInState, searchedString } = this.state;
    const { onSearch } = this;

    console.log("Logged from App");
    const filteredArray = monstersInState
      ? monstersInState.filter((monster) => {
          return monster.name
            .toLocaleLowerCase()
            .includes(searchedString.toLocaleLowerCase());
        })
      : [];
    // console.log(filteredArray);
    return (
      <div className="App">
        <input
          className="search-box"
          type="search"
          placeholder="search monsters"
          onChange={onSearch}
        />
        {this.state.errorMessage ? (
          <h1>Error fetching data</h1>
        ) : (
          <CardList monsters={filteredArray} />
        )}
      </div>
    );
  }
}

export default App;

card-list.component.tsx

import { Component } from "react";
import { Monster } from "../../App";

class CardList extends Component<{ monsters: Monster[] }> {
  render() {
    console.log(this.props.monsters);
    console.log("Logged from CardList");
    const { monsters } = this.props;
    return (
      <div>
        {monsters.map((monster) => {
          return <h1 key={Math.random()}>{monster.name} </h1>;
        })}
      </div>
    );
  }
}

export default CardList;

Now I was expecting the console to have the following output:

Logged from App               *(When App first renders)*
[]                            *(When App first renders and card-list.component is first called)* 
Logged from CardList          *(When App first renders and card-list.component is first called)* 
Logged from App               *(When componentDidMount is called and the state is updated so it triggers a re-render)*
[{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] *(When componentDidMount is called and the state is updated so it triggers a re-render)*
Logged from CardList          *(When componentDidMount is called and the state is updated so it triggers a re-render)*

But Instead what I see is this in the console. I don’t understand why these statements are being logged so many times. Also, what is "installHook.js" and why is it logging stuff to the console?

enter image description here

2

Answers


  1. Let me help you understand what’s happening.

    1."Logged from App" and "Logged from CardList": These log statements are coming from the console.log statements within your render methods in the App and CardList components. These statements will be logged whenever the components render or re-render. Since you have a state update in your componentDidMount method, it will trigger a re-render of the App component, leading to these log statements being printed multiple times.

    2."[]": This empty array is being logged when the CardList component is first rendered. This is expected behavior since the initial state of monsters is an empty array, and the component logs the props.monsters array.

    Now, regarding the presence of "installHook.js" and the additional log statements you’re seeing:

    "installHook.js" is not a part of your codebase. It seems like it’s coming from React DevTools or some other tool you might be using to inspect and debug your React application. It’s not something you need to worry about in your code.

    As for the multiple log statements, it’s important to understand that React components can re-render for various reasons, not just when you manually update the state. Changes to props, state, or the context can trigger a re-render. In your case, the initial render, the re-render caused by componentDidMount, and the re-renders caused by user input (search) all contribute to the multiple log statements you’re observing.

    If you want to log these statements only once during specific scenarios, you can consider using console.log statements outside of the render methods or use console.group and console.groupEnd to group related logs together for better organization.

    Here’s an example of how you could use console.group to group your log statements:

    class App extends Component<any, State> {
      // ...
    
      render() {
        console.group("App Render");
        // ... your rendering code ...
        console.groupEnd();
    
        return (
          <div className="App">
            {/* ... */}
          </div>
        );
      }
    }
    
    class CardList extends Component<{ monsters: Monster[] }> {
      render() {
        console.group("CardList Render");
        // ... your rendering code ...
        console.groupEnd();
    
        return (
          <div>
            {/* ... */}
          </div>
        );
      }
    }
    
    Login or Signup to reply.
  2. If you are just starting. I will highly recommend you to shift on functional component. https://stackoverflow.com/advantages-of-functional-component-in-react-and-why-the-react-team-suggest-its

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search