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?
2
Answers
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 yourrender
methods in theApp
andCardList
components. These statements will be logged whenever the components render or re-render. Since you have a state update in yourcomponentDidMount
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 theprops.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 bycomponentDidMount
, 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 useconsole.group
andconsole.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:
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