无法通过在函数中使用 useState 获取第一个值
Can't get the first value by using useState in a functionn
我需要根据数据值显示文本。通过 运行 代码,我想看到 'Test1: 1' 在我点击按钮后可以显示,但我不能。有什么方法可以做到这一点?
下面是包含代码的示例沙箱 link。
https://codesandbox.io/s/restless-wildflower-9pl09k?file=/src/Parent.js
export default function Parent(props) {
const [data, setData] = useState(0);
const onClick = () => {
setData(1);
console.log(data);
setData(2);
};
return (
<>
<button onClick={onClick}> Click here </button>
{data === 1 ? <div>Test1: {data}</div> : <div>Test2: {data}</div>}
</>
);
}
console.log(data)
没有反映最新数据的原因是 React 管理状态。调用 setState() 是异步的,如果你想依赖状态的新值,正确的方法是传递一个旧状态的函数,返回当前状态。 ref. documentation
useState
返回的setState
函数不直接更新状态。相反,它用于发送 React 将在下一次异步状态更新期间使用的值。 console.log
是一个效果,所以如果你想在每次更改时看到 data
记录,你可以使用 React.useEffect。 运行下面的代码,点击0按钮几次,在浏览器中查看状态变化和效果。
function App() {
const [data, setData] = React.useState(0)
React.useEffect(_ => console.log("data", data), [data])
return <button
onClick={_ => setData(data + 1)}
children={data}
/>
}
ReactDOM.render(<App/>, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
您的评论谈到了网络请求示例。可以设计自定义挂钩以适应复杂的用例并使您的组件易于编写。
function App() {
const [{fetching, error, data}, retry] = useAsync(_ => {
return fetch("https://random-data-api.com/api/users/random_user")
.then(res => res.json())
}, [])
if (fetching) return <pre>Loading...</pre>
if (error) return <pre>Error: {error.message}</pre>
return <div>
<button onClick={retry} children="retry" />
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
}
function useAsync(f, deps) {
const [state, setState] = React.useState({fetching: true})
const [ts, setTs] = React.useState(Date.now())
React.useEffect(_ => {
f()
.then(data => setState({fetching: false, data}))
.catch(error => setState({fetching: false, error}))
}, [...deps, ts])
return [
state,
_ => {
setState({fetching: true, error: null, data: null})
setTs(Date.now())
}
]
}
ReactDOM.render(<App/>, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
我需要根据数据值显示文本。通过 运行 代码,我想看到 'Test1: 1' 在我点击按钮后可以显示,但我不能。有什么方法可以做到这一点?
下面是包含代码的示例沙箱 link。 https://codesandbox.io/s/restless-wildflower-9pl09k?file=/src/Parent.js
export default function Parent(props) {
const [data, setData] = useState(0);
const onClick = () => {
setData(1);
console.log(data);
setData(2);
};
return (
<>
<button onClick={onClick}> Click here </button>
{data === 1 ? <div>Test1: {data}</div> : <div>Test2: {data}</div>}
</>
);
}
console.log(data)
没有反映最新数据的原因是 React 管理状态。调用 setState() 是异步的,如果你想依赖状态的新值,正确的方法是传递一个旧状态的函数,返回当前状态。 ref. documentation
useState
返回的setState
函数不直接更新状态。相反,它用于发送 React 将在下一次异步状态更新期间使用的值。 console.log
是一个效果,所以如果你想在每次更改时看到 data
记录,你可以使用 React.useEffect。 运行下面的代码,点击0按钮几次,在浏览器中查看状态变化和效果。
function App() {
const [data, setData] = React.useState(0)
React.useEffect(_ => console.log("data", data), [data])
return <button
onClick={_ => setData(data + 1)}
children={data}
/>
}
ReactDOM.render(<App/>, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
您的评论谈到了网络请求示例。可以设计自定义挂钩以适应复杂的用例并使您的组件易于编写。
function App() {
const [{fetching, error, data}, retry] = useAsync(_ => {
return fetch("https://random-data-api.com/api/users/random_user")
.then(res => res.json())
}, [])
if (fetching) return <pre>Loading...</pre>
if (error) return <pre>Error: {error.message}</pre>
return <div>
<button onClick={retry} children="retry" />
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
}
function useAsync(f, deps) {
const [state, setState] = React.useState({fetching: true})
const [ts, setTs] = React.useState(Date.now())
React.useEffect(_ => {
f()
.then(data => setState({fetching: false, data}))
.catch(error => setState({fetching: false, error}))
}, [...deps, ts])
return [
state,
_ => {
setState({fetching: true, error: null, data: null})
setTs(Date.now())
}
]
}
ReactDOM.render(<App/>, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>