【问题标题】:what i can do for changing state without re-render我可以做些什么来改变状态而不重新渲染
【发布时间】:2021-06-27 18:46:07
【问题描述】:
import { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchMovies } from "../../feautures/movies/moviesSlice";

import { BiLeftArrow, BiRightArrow } from "react-icons/bi";

import Card from "../Card/Card";
import Slider from "../UI/Slider/Slider";
import Navigation from "../Navigations/Navigation";

import "./MoviesList.scss";
import request from "../../requests";

const MoviesList = () => {
  const dispatch = useDispatch();

  // Current Page

  const [currentPage, setCurrentPage] = useState(1);

  // Handle movies states
  const moviesStatus = useSelector((state) => state.movies.status);
  const moviesState = useSelector((state) => state.movies.movies);
  const moviesError = useSelector((state) => state.movies.error);
  const moviesHeading = useSelector((state) => state.movies.moviesHeading); // It's for pagination

  // Handle header input
  const inputValue = useSelector((state) => state.movies.inputValue);

  // Handle movies heading
  const moviesMoviesHeading = useSelector(
    (state) => state.movies.moviesHeading
  );

  // Movies according input values
  const filteredMovie = moviesState.filter((movie) =>
    movie.original_title.toLowerCase().includes(inputValue)
  );

  // Handle Page Number
  const handlePageNumber = (rotation) => {
    if (rotation === "goPrev" && currentPage >= 2) {
      setCurrentPage((prev) => prev - 1);
      console.log("current page: ", currentPage);
    } else if (rotation === "goNext" && currentPage < 10) {
      setCurrentPage((prev) => prev + 1);
      console.log("current page: ", currentPage);
    }
  };

  // Handle Pagination
  const prevNextPage = () => {
    if (moviesHeading === "POPULAR") {
      console.log("current page", currentPage)
      dispatch(fetchMovies(request.fetchPopular(currentPage)));
    } else if (moviesHeading === "NOW PLAYING") {
      console.log("current page", currentPage)
      dispatch(fetchMovies(request.fetchPopular(currentPage)));
    } else if (moviesHeading === "UP COMING") {
      console.log("current page", currentPage)
      dispatch(fetchMovies(request.fetchUpComing(currentPage)));
    } 
  };

  useEffect(() => {
    if (moviesStatus === "idle") {
      dispatch(fetchMovies(request.fetchPopular()));
    }
  }, [dispatch, moviesStatus]);

  let content;

  if (moviesStatus === "loading") {
    <div>selamlar</div>;
  } else if (moviesStatus === "succeeced") {
    content = (
      <div className="movies__container">
        <BiLeftArrow
          className="movies__arrow movies__arrow--left"
          onClick={() => {
            handlePageNumber("goPrev")
            prevNextPage()
          }}
        />
        {filteredMovie.map((movie) => {
          return <Card movie={movie} key={movie.id} />;
        })}
        <BiRightArrow
          className="movies__arrow movies__arrow--right"
          onClick={() => {
            handlePageNumber("goNext")
            prevNextPage()
          }}
        />
      </div>
    );
  } else if (moviesStatus === "failed") {
    content = <div>{moviesError}</div>;
  }

  return (
    <div className="movies">
      <Slider />
      <div className="movies__heading">{moviesMoviesHeading}</div>
      <Navigation />
      {content}
    </div>
  );
};

export default MoviesList;

大家好。我尝试用 react-redux 制作电影网站。但我卡在某个地方。当我点击右箭头按钮 handlePageNumber 功能增加 currentPage 然后我将此值传递给 dispatch(fetchMovies(request.fetchPopular(currentPage))) 去下一页。但是当我单击向右箭头按钮currentPage 时,状态仍然有1 个值。如果再单击一次currentPage 有2 个值。为什么我第一次单击它时它的值没有2?我猜重新渲染后值会发生变化,如果是这样,我该怎么办?最后,如果我的代码中有什么不好的地方,如果你能告诉我如何编写干净的代码,我将不胜感激。

【问题讨论】:

    标签: javascript reactjs redux react-hooks


    【解决方案1】:

    问题

    问题是 React 状态更新是异步处理的,所以当在下一行调用 prevNextPage() 时,在 handlePageNumber("goPrev")handlePageNumber("goNext") 中排队的状态更新尚未处理,所以 currentPage 仍然是当前渲染周期的值。

    请参阅此 SO answeruseState 设置方法不会立即反映更改)以获取解释。

    解决方案

    您可以从依赖于currentPageuseEffect 调用prevNextPage() 函数。由于prevNextPage 没有在其他地方调用,您可以在useEffect 回调中定义它in 并调用它,或者只是将旧逻辑移动到@ 的主体中987654333@ 回调。您还需要包含 moviesHeading 作为依赖项。

    useEffect(() => {
      if (moviesHeading === "POPULAR") {
        console.log("current page", currentPage)
        dispatch(fetchMovies(request.fetchPopular(currentPage)));
      } else if (moviesHeading === "NOW PLAYING") {
        console.log("current page", currentPage)
        dispatch(fetchMovies(request.fetchPopular(currentPage)));
      } else if (moviesHeading === "UP COMING") {
        console.log("current page", currentPage)
        dispatch(fetchMovies(request.fetchUpComing(currentPage)));
      } 
    }, [currentPage, dispatch, moviesHeading]);
    

    并从点击处理程序中删除调用。

    content = (
      <div className="movies__container">
        <BiLeftArrow
          className="movies__arrow movies__arrow--left"
          onClick={() => {
            handlePageNumber("goPrev");
          }}
        />
        {filteredMovie.map((movie) => {
          return <Card movie={movie} key={movie.id} />;
        })}
        <BiRightArrow
          className="movies__arrow movies__arrow--right"
          onClick={() => {
            handlePageNumber("goNext");
          }}
        />
      </div>
    

    我可能还建议简化您的 handlePageNumber 逻辑以使用数字值而不是字符串,并将值限制在您的页面范围内

    // Handle Page Number
    const handlePageNumber = (nextPage) => {
      setCurrentPage(page => Math.max(1, Math.min(page + nextPage, 10));
    };
    

    将传递1-1 添加到回调以返回页面或前进到下一页。

    content = (
      <div className="movies__container">
        <BiLeftArrow
          className="movies__arrow movies__arrow--left"
          onClick={() => {
            handlePageNumber(-1);
          }}
        />
        {filteredMovie.map((movie) => {
          return <Card movie={movie} key={movie.id} />;
        })}
        <BiRightArrow
          className="movies__arrow movies__arrow--right"
          onClick={() => {
            handlePageNumber(1);
          }}
        />
      </div>
    

    【讨论】:

    • 非常感谢先生。这是一个非常清楚的解释:)
    • 按照您的建议进行操作后,出现此错误。 React Hook useEffect has a missing dependency: 'prevNextPage'. Either include it or remove the dependency array react-hooks/exhaustive-deps.我找不到任何解决方法。
    • @UmutPalabiyik 当然,您可以将整个 prevNextPage 函数定义移动到效果回调中,但最好移动逻辑。我更新了我的答案来解决这个问题。
    • 这次它抛出了这个错误React Hook useEffect has a missing dependency: 'dispatch'. Either include it or remove the dependency array。你可以在有空的时候检查我的仓库吗。它工作得很好,但我可以弄清楚为什么会抛出这个错误:) github.com/UmutPalabiyik/hope-movie-app
    • @UmutPalabiyik 根据react-redux docs dispatch 是一个稳定的参考,但是react hook linting 不知道这一点。这是完全安全的,建议将其添加到依赖数组中。一般来说,你应该添加所有被标记为缺失的依赖项,除非你有充分的理由not
    【解决方案2】:

    react 的 setState 方法似乎异步工作,但您认为它是同步方法。 如果我是你,我将 pagenumber 存储在 redux 状态。我编写动作来处理单击上一个/下一个按钮并发送下一页状态(如果 currentPage = 8,那么我为 nextButton 发送 9,为 prevButton 发送 7),在触发此操作后,我使用 redux-thunk 或 redux- 处理异步操作传奇,每当我从中间件获得响应时,我都会为此异步操作调用成功或失败操作,该操作将处理下一个 redux 状态

    【讨论】:

      猜你喜欢
      • 2019-02-13
      • 1970-01-01
      • 2016-12-30
      • 2017-03-25
      • 2019-11-19
      • 2018-12-31
      • 1970-01-01
      • 2020-04-22
      • 2022-11-06
      相关资源
      最近更新 更多