有没有办法将函数传递给 useState() 的 React Hooks 提供的 "updater" 函数?

is there a way to pass a function to the "updater" function that was provide by the `useState()`'s React Hooks?

我正在探索 React Hooks,到目前为止我想出了这段代码并且正在运行。 现在只是从 giphy API 获取随机 gif 并在您单击按钮时呈现在屏幕上。

import React, {useState} from 'react'
import './App.css';
import axios from 'axios'
const url = process.env.REACT_APP_URL_RANDOM
const apiKey = process.env.REACT_APP_APIKEY

export default function App(){
  const [image, setImage] = useState('')

  const handleRandom = ()=> {
    axios(`${url}?api_key=${apiKey}`).then(response => {
      const img = <img src={response.data.data.image_original_url}
                       alt={response.data.data.title} />
      setImage(img)
    })
  }

  return (
    <div className="App">
      <button onClick={handleRandom}>Get Random Giphy!</button>
      {image}
    </div>
  );
}

我对结果很满意,但是有些事情告诉我,在函数组件之外声明一个函数会更有益。例如,我可能会添加其他按钮点击不同的端点,并且必须在组件内声明此函数我认为就性能而言这不是一个好的做法,TLDR: 我不想要每次渲染组件时声明这些函数。

所以我想到了第二个想法。

import React, {useState} from 'react'
import './App.css';
import axios from 'axios'
const url = process.env.REACT_APP_URL_RANDOM
const apiKey = process.env.REACT_APP_APIKEY

const handleRandom = ()=> {
  console.log("calling handleRandom")
  axios(`${url}?api_key=${apiKey}`).then(response => {
    const img = <img src={response.data.data.image_original_url}
                     alt={response.data.data.title} />
    console.log("returning IMG")
    return img
  })
}

export default function App() {
  console.log("render")
  const [image, setImage] = useState('')
  return (
    <div className="App">
      <button onClick={()=> setImage(handleRandom)}>Get Random Giphy!</button>
      {image}
    </div>
  );
}

所以在这里我会在点击事件上调用 setImage“updater”,参数是函数 handleRandom returns.

我面临的问题是这个。

即使我正在使用 .then() 来解决承诺它看起来不是等待响应并立即调用 render 方法,然后在响应时返回后我们可以看到数据,并且由于已经执行了 render 方法,页面不会更新为新图像。

也许我在这里遗漏了一些东西,或者这应该是尝试使用“useReducer”挂钩的一个很好的例子?

在您的代码中,您没有将 handleRandom 的结果传递给 setImage。

您应该将 handleRandom 函数修改为 return Promise:

return axios(...

然后将结果图像传递给点击处理程序中的 setImage:

onClick={() => handleRandom().then(img => setImage(img))}

要使此方案按预期工作,您可以做的是在承诺执行时创建一个微调器并显示微调器直到承诺完成。然后,一旦承诺完成,您就可以用您的图像替换微调器。

import React, {useState} from 'react'
import './App.css';
import axios from 'axios'
const url = process.env.REACT_APP_URL_RANDOM
const apiKey = process.env.REACT_APP_APIKEY

const handleRandom = ()=> 
{
  console.log("calling handleRandom")

  let img = <p> Loading ... </p>


  axios(`${url}?api_key=${apiKey}`).then(response => {
    img = <img src={response.data.data.image_original_url}
                     alt={response.data.data.title} />
    console.log("returning IMG")

    return img
  })
}

export default function App() {
  console.log("render")
  const [image, setImage] = useState('')
  return (
    <div className="App">
      <button onClick={()=> setImage(handleRandom)}>Get Random Giphy!</button>
      {image}
    </div>
  );
}