我尝试了很多事情,似乎无法理解为什么setTypes不会更新'types'数组?
import { useState, useEffect } from 'react';
import { PostList } from './post-list';
import * as api from '../utils/api';
export const PostSelector = (props) => {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(false);
const [type, setType] = useState('post');
const [types, setTypes] = useState([]);
const fetchTypes = async () => {
setLoading(true);
const response = await api.getPostTypes();
delete response.data.attachment;
delete response.data.wp_block;
const postTypes = response.data;
console.log(response.data); // {post: {…}, page: {…}, case: {…}}
setTypes(postTypes);
console.log(types); // []
// Why types remain empty??
}
const loadPosts = async (args = {}) => {
const defaultArgs = { per_page: 10, type };
const requestArgs = { ...defaultArgs, ...args };
requestArgs.restBase = types[requestArgs.type].rest_base; // Cannot read property 'rest_base' of undefined
const response = await api.getPosts(requestArgs);
console.log(response.data);
}
useEffect(() => {
fetchTypes();
loadPosts();
}, []);
return (
<div className="filter">
<label htmlFor="options">Post Type: </label>
<select name="options" id="options">
{ types.length < 1 ? (<option value="">loading</option>) : Object.keys(types).map((key, index) => <option key={ index } value={ key }>{ types[key].name }</option> ) }
</select>
</div>
);
}
请查看console.log,并注意不同的响应。
我想做的是加载类型列表,在这种情况下是“ post”,“ page”和“ case”,然后根据当前的“ type”呈现一个列表。默认类型为“发布”。
如果我将[types]添加到useEffect。我终于得到了这些值,但组件呈现了不间断的状态。
感谢大家的评论。许多人指出了问题,就是我们设置状态的事实并不意味着它会立即设置,因为它是异步的。
那我们如何解决这个问题?无论原因如何,我们如何完成它?如果我们不知道状态何时可用,我们如何在任何时间使用状态并进行计算?我们如何确保等待所需的一切,然后使用期望的值?
答案 0 :(得分:0)
似乎useState是异步的,调用后不会立即更新该值。
答案 1 :(得分:0)
useState
的setTypes是一个异步函数,因此更改不会立即生效。您可以使用useEffect
检查是否有任何更改
useEffect(()=>{
const defaultArgs = { per_page: 10, type };
const requestArgs = { ...defaultArgs, ...args };
requestArgs.restBase = types;
console.log("types updated",types)
},[types])
您可以删除loadPosts
,因为现在useEffect将在类型更改时运行
答案 2 :(得分:0)
您已将类型声明为数组,但您正在将字典传递给它。 试试这个:
const [types, setTypes] = useState({});
您也不需要致电
loadPosts()
因为useState挂钩将重新渲染您的组件,仅更新所需的内容。
答案 3 :(得分:0)
对于来到这里但无法设置/更新 useState 数组的任何人,您需要使用扩展运算符 (...) 而不仅仅是数组,例如"[...initState]" 而不是 "initState"
//initialise
const initState: boolean[] = new Array(data.length).fill(false);
const [showTable, setShowTable] = useState<boolean[]>([...initState]);
// called from an onclick to update
const updateArray = (index: number) => {
showTable[index] = !showTable[index];
setShowTable([...showTable]);
};
答案 4 :(得分:0)
这不是因为其他答案所说的asynchronous
!!!
您可以通过 console.log
在 return
这样的函数中检查更改。
return (
<div> Hello World!
{
console.log(value) // this will reference every re-render
}
</div>
);
或使用 value
作为依赖项创建一个新的 useEffect,如下所示
React.useEffect(() => {
console.log(value); // this will reference every value is changed
}, [value]);
function App() {
const [value, Setvalue] = React.useState([]);
React.useEffect(() => {
Setvalue([1, 2, 3]);
console.log(value); // this will reference to value at first time
}, []);
return (
<div> Hello World!
{
console.log(value) // this will reference every re-render
}
</div>
);
}
ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>
在此处阅读更多详细信息:useState set method not reflecting change immediately