我创建了一个随机电影生成器,为此,我调用外部API来获取电影,然后从返回的列表中 Select 一部电影.我设法让它像这样工作:

export default function Page() {
  const [movie, setMovie] = useState<Movie>({
    title: ""
  })

  useEffect(() => {
    setNewMovie()
  }, [])

  function setNewMovie() {
    getMoviesRequest().then((newMovies) => {
      const randomIndex = getRandomInt(9)
      const movie = newMovies[randomIndex]
      setMovie(movie)
    })
  }

  return (
    <div>
      <h3>
        {movie.title}
      </h3>
      <button onClick={setNewMovie}>
        Generate New Movie
      </button>
    </div>
  )
}

这段代码的问题是,每当我想设置新电影时,它都必须调用API,这并不理想,因为它需要更长的运行时间.我想要做的是在useEffect钩子内调用一次API,并让返回的电影在组件的整个孔洞生命周期中保持不变,这样我就不必在每次渲染时都拉出电影列表.我正在使用useRef来实现这一点,以下是我try 过的:

export default function Page() {
  const movies = useRef<Movie[]>([])
  const [movie, setMovie] = useState<Movie>({
    title: ""
  })

  useEffect(() => {
    setNewMovies()
    setNewMovie()
  }, [])

  function setNewMovies() {
    getMoviesRequest().then((newMovies) => {
      movies.current = newMovies
    })
  }
  function setNewMovie() {
    const randomIndex = getRandomInt(9)
    const movie = movies.current[randomIndex]
    setMovie(movie)
  }

  return (
    <div>
      <h3>
        {movie.title}
      </h3>
      <button onClick={setNewMovie}>
        Generate New Movie
      </button>
    </div>
  )
}

这不起作用,因为如果我try 访问promise 之外的当前值movies,它似乎没有更新.

我寻找答案,我发现你不能真的从外部访问promise 的价值,除非你是在一个异步函数上,但我已经try 过了,我得到了同样的结果.

有没有办法实现我想要做的事? 谢谢!

推荐答案

您面临的问题是赋值movies.current = newMovies是异步的,所以当您try 在Promise解析后立即访问movies.current值时,它可能还没有更新.

为了确保在访问movies.current值之前对其进行更新,可以使用useEffect挂钩稍微修改代码.以下是应该可以工作的代码的更新版本:

export default function Page() {
  const movies = useRef<Movie[]>([]);
  const [movie, setMovie] = useState<Movie>({ title: "" });

  useEffect(() => {
    getMoviesRequest().then((newMovies) => {
      movies.current = newMovies;
      setNewMovie();
    });
  }, []);

  function setNewMovie() {
    const randomIndex = getRandomInt(9);
    const movie = movies.current[randomIndex];
    setMovie(movie);
  }

  return (
    <div>
      <h3>{movie.title}</h3>
      <button onClick={setNewMovie}>Generate New Movie</button>
    </div>
  );
}

在这个更新的版本中,电影在useEffect钩子中获取并存储在movies ref中.一旦promise 解析并更新了movies.current值,我们就调用setNewMovie函数从列表中 Select 一部随机电影并更新状态.

现在,当组件呈现时,电影将只被提取一次,后续对setNewMovie的调用将从预取的列表中 Select 一部电影,从而避免不必要的API调用.

Javascript相关问答推荐

带对角线分隔符的图像滑动器

JavaScript:循环访问不断变化的数组中的元素

Angular:ng-contract未显示

在NextJS中使用计时器循环逐个打开手风琴项目?

具有相同参数的JS类

如何解决CORS政策的问题

仅针对RTK查询中的未经授权的错误取消maxRetries

康威的生活游戏规则在我的Javascript版本中不起作用.''我做错了什么?

在服务器上放置了Create Reaction App Build之后的空白页面

引用在HTMLAttributes<;HTMLDivElement>;中不可用

Angular 中的类型错误上不存在获取属性

为什么我的自定义元素没有被垃圾回收?

为什么可选参数的顺序会导致问题?

Next.js中的服务器端组件列表筛选

如何使本地html页面在重新加载时保持当前可隐藏部分的打开状态?

bootstrap S JS赢得了REACT中的函数/加载

P5play SecurityError:无法从';窗口';读取命名属性';Add';:阻止具有源的帧访问跨源帧

表单数据中未定义的数组键

如何在Highlihte.js代码区旁边添加行号?

我们是否可以在reactjs中创建多个同名的路由