【问题标题】:useState on React Hooks not updating ArrayReact Hooks 上的 useState 不更新数组
【发布时间】:2020-06-03 03:03:44
【问题描述】:

我尝试了很多东西,但似乎无法理解为什么 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”。

如果我将 [types] 添加到 useEffect.我终于得到了值,但组件不停地呈现。

感谢大家的 cmets。很多人都指出了这个问题,因为我们设置状态并不意味着它会立即设置,因为它是异步的。

那我们如何解决这个问题呢?不管是什么原因,我们如何完成它?如果我们不知道它何时可用,我们如何在任何时间点使用我们的状态并根据我们的状态执行计算?我们如何确保我们等待所需的一切,然后使用我们期望的值?

【问题讨论】:

  • 尝试使用扩展运算符。 setTypes([...postTypes]);
  • 看起来 response.data 是一个对象,而不是一个数组
  • 这回答了你的问题。 stackoverflow.com/questions/60294328/…
  • 欢迎您,但我不明白重新渲染如何与作为对象的类型相关联?
  • @drjorgepolanco,谢谢,我希望您已经阅读了本文中的 cmets ;) 很高兴它对您有所帮助。编码愉快。

标签: javascript reactjs react-hooks use-state


【解决方案1】:

好的,简短的回答是由于Closures

这不是因为asynchronous 正如其他答案所说的那样!!!


解决方法(☞゚ヮ゚)☞

您可以像这样通过console.logreturn 函数检查更改。

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

【讨论】:

  • 这能回答你的问题吗?如果您需要任何帮助,请告诉我^^! @drjorgepolinco
【解决方案2】:

对于任何来到这里但无法设置/更新 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]);
  };

【讨论】:

    【解决方案3】:

    您已将您的类型声明为一个数组,但您正在将一个字典字典传递给它。 试试这个:

    const [types, setTypes]     = useState({});
    

    你也不需要打电话

    loadPosts()
    

    因为 useState 钩子会重新渲染您的组件,只更新需要的内容。

    【讨论】:

      【解决方案4】:

      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 将在类型更改时运行

      【讨论】:

      • 如果我通过 [types] 它永远不会停止渲染。
      • 这很奇怪。您能否在stackblitz.com/edit/react-leukwv 上提供一些示例代码,以便我进行测试。
      【解决方案5】:

      好像useState是异步的,调用后不会立即更新值。

      Review this same case here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-19
        • 1970-01-01
        • 2020-11-15
        • 1970-01-01
        • 2022-09-30
        • 2019-06-26
        相关资源
        最近更新 更多