繁体   English   中英

为什么 React-app 状态不在这里重新渲染? 如何让状态及时更新

[英]Why is React-app state not re-rendering here? How to get state to update in time

我想弄清楚这是如何工作的。

我有一个“pageCounter”变量,用于跟踪当前页面(点击上一个/下一个按钮时更新),当它更新时,我想将选项卡的标题更改为新页面数据。

当我单击下一步按钮时,它不会呈现,除非我单击它两次并且控制台日志显示它尚未更新。 但是当我点击下一步后点击我的“日志”按钮时,它说它已经更新了?

我已经完成了我的研究并假设这是由于“setState”函数的异步性质。 但是,我不确定如何解决这个问题?

我尝试将 updateTitles 函数放在useEffect钩子中,但是无论我是将函数的内容复制到其中还是在钩子中调用函数,都会出现错误。

我错过了什么?

updateTitles的内容放入useEffect时出现的错误是:

超过最大更新深度。

这是组件代码:(代码沙箱在这里)

import React from "react";
import "./styles.css";

import React, { useState, useEffect } from "react";

function Options() {
  // Component States
  const [pageCounter, setPage] = useState(1);
  const [optionTitles, setOptionTitles] = useState({
    Option1: "End of Lease Clean",
    Option2: "Regular House Cleaning",
    Option3: "Other Clean"
  });
  //Component Variables
  const pageOneTitles = {
    Option1: "End of Lease Clean",
    Option2: "Regular House Cleaning",
    Option3: "Other Clean"
  };
  const pageTwoTitles = {
    Option1: "Blah1",
    Option2: "Blah12",
    Option3: "Blah13"
  };
  const pageThreeTitles = {
    Option1: "MrMagoo",
    Option2: "Nins",
    Option3: "Pottao"
  };

  function updateTitles() {
    switch (pageCounter) {
      case 1:
        setOptionTitles(pageOneTitles);
        break;
      case 2:
        setOptionTitles(pageTwoTitles);
        break;
      case 3:
        setOptionTitles(pageThreeTitles);
        break;
      default:
        console.log("default");
        break;
    }
  }

  function nextPage() {
    if (pageCounter < 3) {
      setPage(pageCounter + 1);
      updateTitles();
      console.log(pageCounter);
    }
  }

  function prevPage() {
    if (pageCounter > 1) {
      setPage(pageCounter - 1);
      updateTitles();
      console.log(pageCounter);
    }
  }

  function printLog() {
    console.log(pageCounter);
  }

  return (
    <div id="options">
      <button onClick={prevPage} id="next">
        Back
      </button>
      <CardOption title={optionTitles.Option1} />
      <CardOption title={optionTitles.Option2} />
      <CardOption title={optionTitles.Option3} />
      <p>{}</p>
      <button onClick={nextPage} id="next">
        Next
      </button>
      <button onClick={printLog} id="next">
        log
      </button>
    </div>
  );
}
function CardOption(props) {
  return (
    <div className="card">
      <h2>{props.title}</h2>
    </div>
  );
}

export default Options;

这是我尝试使用钩子 useEffect 时的代码,但我收到一条错误消息,指出“已超过最大更新深度”。

        import React, { useState, useEffect } from "react";

function Options() {
  // Component States
  const [pageCounter, setPage] = useState(1);
  const [optionTitles, setOptionTitles] = useState({
    Option1: "Page 1.11",
    Option2: "Regular House Cleaning",
    Option3: "Other Clean"
  });
  //Component Variables
  const pageOneTitles = {
    Option1: "Page 1.1",
    Option2: "Regular House Cleaning",
    Option3: "Other Clean"
  };
  const pageTwoTitles = {
    Option1: "Page 2.1",
    Option2: "Blah12",
    Option3: "Blah13"
  };
  const pageThreeTitles = {
    Option1: "Page 3.1",
    Option2: "Nins",
    Option3: "Pottao"
  };

  useEffect(() => {
    switch (pageCounter) {
      case 1:
        setOptionTitles(pageOneTitles);
        break;
      case 2:
        setOptionTitles(pageTwoTitles);
        break;
      case 3:
        setOptionTitles(pageThreeTitles);
        break;
      default:
        console.log("default");
        break;
    }
  }, [pageCounter, pageOneTitles, pageTwoTitles, pageThreeTitles]);

  function nextPage() {
    if (pageCounter < 3) {
      setPage(pageCounter + 1);
      console.log(pageCounter);
    }
  }

  function prevPage() {
    if (pageCounter > 1) {
      setPage(pageCounter - 1);
      console.log(pageCounter);
    }
  }

  function printLog() {
    console.log(pageCounter);
  }

  return (
    <div id="options">
      <button onClick={prevPage} id="next">
        Back
      </button>
      <CardOption title={optionTitles.Option1} />
      <CardOption title={optionTitles.Option2} />
      <CardOption title={optionTitles.Option3} />
      <p>{pageCounter}</p>
      <button onClick={nextPage} id="next">
        Next
      </button>
      <button onClick={printLog} id="next">
        log
      </button>
    </div>
  );
}
function CardOption(props) {
  return (
    <div className="card">
      <h2>{props.title}</h2>
    </div>
  );
}

export default Options;

这是 useEffect 钩子的代码沙箱: https ://codesandbox.io/s/thirsty-panini-mkdzh

useEffect为每个状态更新运行。 确保将其 deps 设置为

useEffect(()=> {
   // do stuff with pagecounter , which is updated count

},[pageCount])

如果您只想在安装时运行一次

useEffect(()=> {
   // do stuff with pagecounter , which is initial count

},[])

useEffect 也会在第一次渲染时运行,避免在初始渲染时运行它,比如

    const [pageCount, setPageCount] = useState(0)
    useEffect(()=> {
     if (pageCount===0){
       //this prevent to run on first render
       return 
     }
     // code here will only run on updating state
    },[pageCount])

我认为这应该有效:

import React, { useState, useEffect } from "react";

function Options() {
  // Component States
  const [pageCounter, setPage] = useState(1);
  const [optionTitles, setOptionTitles] = useState({
    Option1: "End of Lease Clean",
    Option2: "Regular House Cleaning",
    Option3: "Other Clean"
  });
  //Component Variables
  const pageOneTitles = {
    Option1: "End of Lease Clean",
    Option2: "Regular House Cleaning",
    Option3: "Other Clean"
  };
  const pageTwoTitles = {
    Option1: "Blah1",
    Option2: "Blah12",
    Option3: "Blah13"
  };
  const pageThreeTitles = {
    Option1: "MrMagoo",
    Option2: "Nins",
    Option3: "Pottao"
  };

  function updateTitles() {
    switch (pageCounter) {
      case 1:
        setOptionTitles(pageOneTitles);
        break;
      case 2:
        setOptionTitles(pageTwoTitles);
        break;
      case 3:
        setOptionTitles(pageThreeTitles);
        break;
      default:
        console.log("default");
        break;
    }
  }

  function nextPage() {
    if (pageCounter < 3) {
      setPage(prev => prev + 1, updateTitles());
      console.log(pageCounter);
    }
  }

  function prevPage() {
    if (pageCounter > 1) {
      setPage(pageCounter - 1, updateTitles());
      console.log(pageCounter);
    }
  }

  function printLog() {
    console.log(pageCounter);
  }

  return (
    <div id="options">
      <button onClick={() => prevPage() } } id="next">
        Back
      </button>
      <CardOption title={optionTitles.Option1} />
      <CardOption title={optionTitles.Option2} />
      <CardOption title={optionTitles.Option3} />
      <p>{}</p>
      <button onClick={() => { nextPage() }} id="next">
        Next
      </button>
      <button onClick={() => { printLog() }} id="next">
        log
      </button>
    </div>
  );
}
function CardOption(props) {
  return (
    <div className="card">
      <h2>{props.title}</h2>
    </div>
  );
}

export default Options;

onClick应该传递一个回调来调用函数而不是调用它。 此外,我没有看到您在代码片段中使用useEffect

结合useEffect()useCallback()函数。

  useEffect(()=> {
    updateTitles();

 },[pageCounter]);

  const updateTitles = useCallback(() => {
    switch (pageCounter) {
      case 1:
        setOptionTitles(pageOneTitles);
        break;
      case 2:
        setOptionTitles(pageTwoTitles);
        break;
      case 3:
        setOptionTitles(pageThreeTitles);
        break;
      default:
        console.log("default");
        break;
    }
  }, [pageCounter]);

nextPage()prevPage()删除updateTitles()函数

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM