我正在使用带有钩子的功能组件。我需要更新状态在父母从一个孩子。我使用的道具功能在父母。
一切都很好,除了我的道具函数是得到以前的状态,而不是当前的状态。我的道具函数在useState钩子设置当前状态之前执行。
我怎么能在useState调用后等待回调函数执行。我正在寻找类似setState(状态,回调)从基于类的组件。
下面是代码片段:
function Parent() {
const [Name, setName] = useState("");
getChildChange = getChildChange.bind(this);
function getChildChange(value) {
setName(value);
}
return <div> {Name} :
<Child getChildChange={getChildChange} ></Child>
</div>
}
function Child(props) {
const [Name, setName] = useState("");
handleChange = handleChange.bind(this);
function handleChange(ele) {
setName(ele.target.value);
props.getChildChange(collectState());
}
function collectState() {
return Name;
}
return (<div>
<input onChange={handleChange} value={Name}></input>
</div>);
}
实际上,你应该避免在使用react钩子时使用这个。它会产生副作用。这就是react团队创建react钩子的原因。
如果你删除了试图绑定它的代码,你可以简单地将父的setName传递给子,并在handleChange中调用它。清洁代码!
function Parent() {
const [Name, setName] = useState("");
return <div> {Name} :
<Child setName={setName} ></Child>
</div>
}
function Child(props) {
const [Name, setName] = useState("");
function handleChange(ele) {
setName(ele.target.value);
props.setName(ele.target.value);
}
return (<div>
<input onChange={handleChange} value={Name}></input>
</div>);
}
此外,您不必创建Name的两个副本(一个在Parent中,另一个在Child中)。坚持“单一真相来源”原则,孩子不必拥有国家名称,而是从父母那里接受。清洁节点!
function Parent() {
const [Name, setName] = useState("");
return <div> {Name} :
<Child setName={setName} Name={Name}></Child>
</div>
}
function Child(props) {
function handleChange(ele) {
props.setName(ele.target.value);
}
return (<div>
<input onChange={handleChange} value={props.Name}></input>
</div>);
}
我们可以编写自定义函数,它将在状态发生任何变化时调用callBack函数
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const useStateCallbackWrapper = (initilValue, callBack) => {
const [state, setState] = useState(initilValue);
useEffect(() => callBack(state), [state]);
return [state, setState];
};
const callBack = state => {
console.log("---------------", state);
};
function App() {
const [count, setCount] = useStateCallbackWrapper(0, callBack);
return (
<div className="App">
<h1>{count}</h1>
<button onClick={() => setCount(count + 1)}>+</button>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
`
function Parent() {
const [Name, setName] = useState("");
getChildChange = getChildChange.bind(this);
function getChildChange(value) {
setName(value);
}
return <div> {Name} :
<Child getChildChange={getChildChange} ></Child>
</div>
}
function Child(props) {
const [Name, setName] = useState("");
handleChange = handleChange.bind(this);
collectState = collectState.bind(this);
function handleChange(ele) {
setName(ele.target.value);
}
function collectState() {
return Name;
}
useEffect(() => {
props.getChildChange(collectState());
});
return (<div>
<input onChange={handleChange} value={Name}></input>
</div>);
}
useEffect作为componentDidMount, componentDidUpdate,所以更新状态后它将工作
你可以使用useEffect/useLayoutEffect来实现:
const SomeComponent = () => {
const [count, setCount] = React.useState(0)
React.useEffect(() => {
if (count > 1) {
document.title = 'Threshold of over 1 reached.';
} else {
document.title = 'No threshold reached.';
}
}, [count]);
return (
<div>
<p>{count}</p>
<button type="button" onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
);
};
如果你想防止回调在第一次渲染时运行,请调整之前的版本:
const SomeComponent = () => {
const [count, setCount] = React.useState(0)
const didMount = React.useRef(false);
React.useEffect(() => {
if (!didMount.current) {
didMount.current = true;
return;
}
if (count > 1) {
document.title = 'Threshold of over 1 reached.';
} else {
document.title = 'No threshold reached.';
}
}, [count]);
return (
<div>
<p>{count}</p>
<button type="button" onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
);
};
这里有更多关于它的信息。