如何在useEffect内调用一个prop函数?

3

我正在尝试移除React组件上的警告。

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

这是一个组件

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

如果我试图在handleClick函数中删除handleChange函数的注释,那么handleChange函数将无法正常工作。

如果我尝试将useEffect替换为以下内容:

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

或者

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

IT尝试渲染太多次,导致出现错误。

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

实际上它像第一段代码一样工作,但我仍然收到警告。

这是父级原始的handleChange函数。

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

父组件
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>
)

}


为什么你在 useEffect 里调用这个 prop? - undefined
它来自一个上层组件const handleChange = (name, value) => { setSelected({ ...selected, [name]: value }) } - undefined
但这不是为什么呢? - undefined
1
为什么不在handleClick函数内部调用handleChange呢?你已经将其注释掉了。它不应该需要放在一个useEffect中。 - undefined
我也认为你应该在点击处理程序中调用它,而不需要使用useEffect。另外,如果父组件已经可以访问标签,那么传递标签给handleChange回调似乎有些奇怪。 - undefined
显示剩余2条评论
2个回答

2
在将函数作为prop传递之前,您应该使用useCallback hook进行包装。文档可以在此处找到:这里

您不应该那样使用useEffect。

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

我在努力尝试,但是没有成功,也许是我写错了。你有什么例子吗? - undefined
你能把你正在定义回调函数的组件贴出来吗? - undefined
是的,它就是"父组件"。 - undefined
哎呀,这段代码有点乱。通过 useCallback 钩子的使用,可以明显看出你确实有一个循环。 - undefined
怎样才能最好地编写那个useCallback函数呢? - undefined

0
为什么不从props中解构出

1
请问您能否将代码放在回答中?仅提供链接的回答在链接的网站消失或无法访问时并不实用。 - undefined
1
抱歉,但它仍然在React控制台上尝试渲染太多次。 - undefined
试试这个沙盒 export default function App() { const [selected,setSelected] = React.useState({}) const handleChange = (name,value)=>{ setSelected({...selected, [name]:value}) } return ( <div className="App"> <SelectButton label="标签" handleChange={handleChange} /> </div> ); } - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接