简体   繁体   中英

How to call a prop function inside useEffect?

Im triying to remove this warning on a react component

Line 19:8:  React Hook useEffect has a missing dependency: 'handleChange'. Either include it or remove the dependency array  react-hooks/exhaustive-deps

this is the component

const SelectButton = (props)=>{
    const [activeState, setActiveState] = useState(false)
    const label = props.label
    
    const handleClick = () =>{
        setActiveState(!activeState)
        //props.handleChange(label,activeState)
    }

    const handleChange = props.handleChange
    
    useEffect(()=>{
        handleChange(label,activeState)
    }, [label,activeState])

    return(
        <button 
                type="button" 
                onClick={handleClick} 
                className={"container-form-button "+(activeState?"active":"")}>
                    {label}
        </button>
    )
}

if i tried to remove the comments on handleChange inside of handleClick, handleChange didn´t works correctly

if i tried to change useEffect for something like this

useEffect(()=>{
   handleChange(label,activeState)
}, [label,activeState,handleChange])

or

useEffect(()=>{
       props.handleChange(label,activeState)
    }, [label,activeState,props.handleChange])

it try to reder to many times and throw this error.

Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render

Actually it works like first code, but im still having the warning

this is the parent original handleChange

const handleChange = (name,value)=>{
        setSelected({...selected, [name]:value})
    }

the parentComponent

const CategorySearcher = (props) =>{
const ciudades = ["Guadalajara","Zapopan","Tlajomulco"]
const tipos = ["Casa","Departamento"]

const [selected, setSelected] = useState({})

const handleChange = useCallback(
    (label,value) => {
            setSelected({...selected, [label]:value})
        },
    [selected],
)
useEffect(() => {
    console.log(selected);
}, [selected])

const cities = ciudades.map((city)=><SelectButton key={city} handleChange={handleChange} label={city}/>)

const types = tipos.map((tipo)=><SelectButton key={tipo} handleChange={handleChange} label={tipo}/>)

let history = useHistory();

const setUrlSearch = ()=>{
    let urlSearch = "search/q="
    let attToSearch = []
    for (var key in selected) {
        selected[key]?attToSearch.push(key):console.log("Nada")
    }
    /*
    attToSearch.forEach((it)=>{
        urlSearch = urlSearch+"&"+it
    })*/
    console.log(urlSearch);
    history.push(urlSearch+attToSearch)
}

return (
    <section className="general-container">
        <div className="container-box">
            <span className="container_title">
                Tu nuevo hogar esta aquí :)
            </span>
        </div>
        
        <div className="container-form">
            <form className="container-form-box">
                <div className="container-form-cities">
                    <div className="container-form-subtitle">
                    Ciudades
                    </div>
                    <div className="container-buttons">
                        {cities}
                    </div>
                </div>

                <div className="container-form-cities">
                    <div className="container-form-subtitle">Tipo de hogar</div>
                    <div className="container-buttons">
                        {types}
                    </div>
                </div>

                <div className="container-box-button">
                    <button className="button-form-CTA" onClick={setUrlSearch}>
                        Buscar
                    </button>
                </div>

            </form>
        </div>
    </section>
)

}

You should be wrapping your function with the useCallback hook before passing it as a prop. Documentation can be found here .

You shouldn't be using useEffect like that.

const SelectButton = ({ label, handleChange }) => {
  const [activeState, setActiveState] = React.useState(false);

  const handleClick = () => {
    const newState = !activeState
    setActiveState(newState);
    handleChange(label, newState);
  };

  return (
    <button
      type="button"
      onClick={handleClick}
      className={"container-form-button " + (activeState ? "active" : "")}
    >
      {label}
    </button>
  );
};

Why don't you destructure label and handleChange from props? Check out this sandbox, this does not cause any infinite update loop: codesandbox

import React from "react";

export default function App() {
  const handleChange = () => console.log("handling change");

  return (
    <div className="App">
      <SelectButton label="Label" handleChange={handleChange} />
    </div>
  );
}

const SelectButton = ({ label, handleChange }) => {
  const [activeState, setActiveState] = React.useState(false);

  const handleClick = () => {
    setActiveState(!activeState);
  };

  React.useEffect(() => {
    handleChange(label, activeState);
  }, [label, activeState, handleChange]);

  return (
    <button
      type="button"
      onClick={handleClick}
      className={"container-form-button " + (activeState ? "active" : "")}
    >
      {label}
    </button>
  );
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM