1

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>
    )
}

2 Answers 2

2

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)

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

1 Comment

Thanks for the reply and and your comment, this helps a lot!
1

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>
 )
}

Comments

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.