Reputation: 59
I am inputting car brands into an input box, which then are saved below the textbox in a list by pressing the "Save" button. My other component "Info" should set a text div to display a string when there is over 5 items in the list.
I am doing this without classes and need to use the Info component to do the actual rendering of the string "There's at least 5 car brands". The amount of items in the list needs to be passed from the Cars function as props to the Info component.
The adding is working, but when I am trying to return the count variable as props to the getCount component with , it crashes due to too many re-renders and I have been unable to get this working.
const Cars = () => {
const [car, setCar] = useState('');
const [list, setList] = useState([]);
const handleClick=(e)=>{
e.preventDefault();
setList((ls)=>[...ls, car])
setCar("");
}
const getCount = () => { //This only feature is to return the size of the list
let count = 0;
count = list.length;
return count;
}
return (
<div>
<Info data={getCount()}/> //This is crashing the app from too many re-renders
<h1>Enter a car brand!</h1>
<input type="text" value={car} onChange={(e)=>setCar(e.target.value)}/>
<button type="button" onClick={handleClick}>Save</button>
<ul>
{
list.map((car, i) => (
<li key = {i}>{car}</li>
))
}
</ul>
</div>
)
}
//This components itself works, tried testing with an actual
const Info = (props) => { //number input and it works. But with getCount input it crashes
const [text, setText] = useState('');
if(props.data > 2) {
setText("There's at least 5 car brands");
}
return (
<div>
<h2>{text}</h2>
</div>
)
}
Upvotes: 1
Views: 71
Reputation: 148
When list is change then only get count show
const Cars = () => {
const [car, setCar] = useState('');
const [list, setList] = useState([]);
const handleClick=(e)=>{
e.preventDefault();
setList((ls)=>[...ls, car])
setCar("");
}
useEffect(()=>{
getCount()
},[list])
const getCount = () => { //This only feature is to return the size of the list
let count = 0;
count = list.length;
return count;
}
return (
<div>
<Info data={() => getCount()}/> //You can change here
<h1>Enter a car brand!</h1>
<input type="text" value={car} onChange={(e)=>setCar(e.target.value)}/>
<button type="button" onClick={handleClick}>Save</button>
<ul>
{
list.map((car, i) => (
<li key = {i}>{car}</li>
))
}
</ul>
</div>
)
}
Or You will do this
const Cars = () => {
const [car, setCar] = useState('');
const [list, setList] = useState([]);
const [listCount, setlistCount] = useState(0);
const handleClick=(e)=>{
e.preventDefault();
setList((ls)=>[...ls, car])
setCar("");
}
useEffect(()=>{
getCount()
},[list])
const getCount = () => { //This only feature is to return the size of the list
setlistCount(list.length)
}
return (
<div>
<Info data={listCount}/> //You can change here
<h1>Enter a car brand!</h1>
<input type="text" value={car} onChange={(e)=>setCar(e.target.value)}/>
<button type="button" onClick={handleClick}>Save</button>
<ul>
{
list.map((car, i) => (
<li key = {i}>{car}</li>
))
}
</ul>
</div>
)
}
Or You will do this
const Cars = () => {
const [car, setCar] = useState('');
const [list, setList] = useState([]);
const handleClick=(e)=>{
e.preventDefault();
setList((ls)=>[...ls, car])
setCar("");
}
return (
<div>
<Info data={list.length}/> //You can change here
<h1>Enter a car brand!</h1>
<input type="text" value={car} onChange={(e)=>setCar(e.target.value)}/>
<button type="button" onClick={handleClick}>Save</button>
<ul>
{
list.map((car, i) => (
<li key = {i}>{car}</li>
))
}
</ul>
</div>
)
}
Upvotes: 1
Reputation: 370659
If you call a state setter on render, that'll cause a re-render.
If your app's state is such that the condition that results in the state setter being called is true, you'll get infinite re-renders.
In this case, there's no need for state in the Info - just use a plain variable that alternates between the empty string and the "There's at least 5 car brands" string.
const Info = ({ data }) => {
const text = data > 2 ? 'There's at least 5 car brands' : '';
return (
<div>
<h2>{text}</h2>
</div>
);
};
Also
<Info data={getCount()}/>
simplifies to
<Info data={list.length} />
or you might rename the prop to listLength
. (Precise variable names make code more readable and can reduce bugs)
Upvotes: 2