Home > front end >  ReactJS functional component variable passing
ReactJS functional component variable passing

Time:02-03

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

CodePudding user response:

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)

CodePudding user response:

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>
 )
}
  •  Tags:  
  • Related