简体   繁体   English

如何在 useEffect 中使用 useState,访问组件挂载时更新的 useState 值?

[英]How to use useState inside useEffect, accessing the updated useState value on component mount?

I'm trying to build a code that can or cannot receive querystrings.我正在尝试构建一个可以或不能接收查询字符串的代码。 If it receives all querystrings, I want to execute a function:如果它接收到所有查询字符串,我想执行一个 function:

  // state for query
  const [query, setQuery] = useState({
    periodicity: "",
    stock: "",
    date: moment().subtract(1, "y"),
    investment: ""
  });


  // check if there are query strings
  function useQuery() {
    return new URLSearchParams(useLocation().search);
  }
  let qs = useQuery();
  let queries = {};

  // set query strings received
  useEffect(() => {
    if (qs.has("periodicity")) {
      queries.periodicity = qs.get("periodicity");
    }
    if (qs.has("start_date")) {
      queries.date = moment(qs.get("start_date"));
    }
    if (qs.has("symbol")) {
      queries.stock = { value: qs.get("symbol"), label: qs.get("symbol") };
    }
    if (qs.has("investment")) {
      queries.investment = qs.get("investment");
    }
    setQuery({ ...query, ...queries });
    if (
      query.periodicity !== "" &&
      query.stock !== "" &&
      query.investment !== ""
    ) {
      simulate();
    }
  }, []);

The initial state is the query state. initial statequery state。 What I'm doing is, on component mount, verify if there are query strings and change the component to match the query strings received.我正在做的是,在组件挂载时,验证是否有查询字符串并更改组件以匹配收到的查询字符串。

The problem is, I never enter the last if (query.periodicity.== "" && query.stock !== "" && query.investment !== "") .问题是,我从不输入最后一个if (query.periodicity.== "" && query.stock !== "" && query.investment !== "") I know it's because useState will update the state on the next component mount, and that useEffect is only running once, before useState updates the state.我知道这是因为useState将在下一个组件安装时更新 state,并且useEffect只运行一次,然后useState更新 state。 But how can I fix it without entering in a loop?但是如何在不进入循环的情况下修复它?

I can't put the query in the useEffect dependency array, because if the user fills all data and the query state becomes populated, I don't want to automatically run the simulate() function, because the user needs to click on a button.我不能把query放在useEffect依赖数组中,因为如果用户填写了所有数据并且query state 被填充,我不想自动运行simulate() function,因为用户需要点击一个按钮. I just want to run it automatically if I received all the query strings needed when entering this page.如果我收到进入此页面时所需的所有查询字符串,我只想自动运行它。

Thanks in advance!提前致谢!

You can set the state in the component function body and check it in the useEffect callback:您可以在组件 function 主体中设置 state 并在useEffect回调中检查它:

function App(props) {
  const initialState = {
    periodicity: "",
    stock: "",
    date: "2019-01-01",
    investment: ""
  };

  let qs = useQuery();
  let queries = {};

  if (qs.has("periodicity")) {
    queries.periodicity = qs.get("periodicity");
  }
  if (qs.has("start_date")) {
    queries.date = qs.get("start_date");
  }
  if (qs.has("symbol")) {
    queries.stock = { value: qs.get("symbol"), label: qs.get("symbol") };
  }
  if (qs.has("investment")) {
    queries.investment = qs.get("investment");
  }

  const [query, setQuery] = useState(
    receivedQueryString(queries) ? queries : initialState
  );

  /*
  *  Rest of the component implementation
  */

  function receivedQueryString(query) {
    return (
      query.periodicity != "" && query.stock != "" && query.investment != ""
    );
  }

  useEffect(() => {
    if (receivedQueryString(query)) {
      simulate();
    }
  });

  function simulate() {
    props.history.push(
      `/?periodicity=${query.periodicity}&start_date=${query.date}&symbol=${
        query.stock.value
      }&investment=${query.investment}`
    );
    // calls API
  }

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

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

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