【问题标题】:Why is my promise not properly setting my state?为什么我的承诺没有正确设置我的状态?
【发布时间】:2019-10-20 21:20:45
【问题描述】:

我有一个调用我的 Rails 后端的 React 前端,我正在尝试编写一个在此执行的 Promise。但是,我不明白我写的承诺有什么问题。我可以看到后端以 OK 响应,但是我无法将组件的状态设置为我正在检索的数据

const [things, setThings] = useState([])

useEffect(() => {
    fetchThings();
}, [])

function getThingsPromise(){
    return new Promise((resolve, reject) => {
        const url = "/api/v1/things/index";
        fetch(url).then(response => {
            if (response.ok) {
                return response.json();
            }
            throw new Error('Network response was not ok.');
        }).then(response => resolve(response))
    })
}

function fetchThings() {
    getThingsPromise().then((response) => {
        setThings(response)
    })
    console.log(things)
}

【问题讨论】:

  • getThingsPromise 中的代码工作正常(我已经用公共 api 尝试过)- 控制台上是否有任何错误?
  • 没有错误——27号的console.log只返回一个空数组
  • 我不确定,但 console.log 不应该在 then 回调中吗?我认为您正在尝试记录事物,但由于承诺是异步的,因此尚未填充它
  • 状态设置正确,但要等下一次渲染才能看到。
  • 将控制台日志移到 fetch things 函数之外,您将在最终设置状态并重新渲染组件时看到日志(setState 已添加到 javascript 队列中,并且在其中不可用下一行代码)

标签: ruby-on-rails reactjs


【解决方案1】:

你实际上没有设置数据的问题,你只是把你的console.log放在了错误的地方。
在反应中设置状态是异步发生的。在您记录您的状态时,它尚未使用收到的数据进行更新。它将在下次组件重新呈现时可用,但是您的 fetchThings() 函数没有被执行,因此您看不到日志。
如果您将 console.log 放在组件主体中,您可以观察到这一点:
在第一次渲染时,它会记录仍然为空的状态,然后在接收到数据后状态会更新,这会导致组件重新渲染。在第二次渲染中,数据将可用。

function App() {
  const [things, setThings] = useState([]);

  useEffect(() => {
    fetchThings();
  }, []);

  function getThingsPromise() {
    return new Promise((resolve, reject) => {
      const url = "/api/v1/things/index";
      fetch(url)
        .then(response => {
          if (response.ok) {
            return response.json();
          }
          throw new Error("Network response was not ok.");
        })
        .then(response => resolve(response));
    });
  }

  function fetchThings() {
    getThingsPromise().then(response => {
      setThings(response);
    });
    console.log("The state hasn't been updated yet:", things);
  }

  // this logs the state every time the component renders
  console.log("First it's empty, then we have data:", things);

  return <div>result: {JSON.stringify(things)}</div>;
}

您可以在此处使用该示例: https://codesandbox.io/s/hooks-setstate-log-hjle1?fontsize=14

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-19
    • 2021-11-23
    • 2021-02-12
    • 2020-08-21
    • 1970-01-01
    • 2018-07-09
    • 1970-01-01
    • 2021-10-20
    相关资源
    最近更新 更多