简体   繁体   English

对 lodash 和 setInterval 的反应问题

[英]React issue with lodash and setInterval

I have an issue with using Lodash + setInterval.我在使用 Lodash + setInterval 时遇到问题。

What I want to do: Retrieve randomly one element of my object every 3 seconds我想做的是:每 3 秒随机检索我的 object 中的一个元素

this is my object:这是我的 object:

    const [table, setTable]= useState ([]);

so I start with that:所以我从那开始:

const result = _.sample(table);
   console.log(result);

console give => Object { label: "Figue", labelEn: "fig" } console give => Object { label: "Figue", labelEn: "fig" }

But if a add:但如果添加:

const result = _.sample(table);
   console.log(result.label);

console give => TypeError: result is undefined控制台给出 => 类型错误:结果未定义

Beside that I tried to add setInterval and also try with useEffect but or code crash or console give me two numbers every 3 second => 2,6,2,6......除此之外,我尝试添加 setInterval 并尝试使用 useEffect 但是或代码崩溃或控制台每 3 秒给我两个数字 => 2,6,2,6 ......

Ciao, supposing that table object is correclty filled, you could use lodash and setInterval to get random object of table using useEffect and useRef hooks like:再见,假设table object 已正确填充,您可以使用lodashsetInterval使用useEffectuseRef挂钩随机获取table object,例如:

const interval = useRef(null);
  useEffect(() => {
    if (!interval.current) {
      interval.current = setInterval(() => {
        const result = _.sample(table);
        console.log(result.label);
      }, 3000);
    }
  }, [table]);

Then to clean setInterval when component will be unmount you could use another useEffect in this way:然后要在卸载组件时清理setInterval ,您可以通过这种方式使用另一个useEffect

useEffect(() => {
    return () => {
      clearInterval(interval.current);
      interval.current = null;
    };
  }, []);

EDIT编辑

After your explanation, I found the cause of your problem.经过你的解释,我找到了你问题的原因。 Before start setInterval you have to wait that table was filled with values (otherwise you get an error).在开始setInterval之前,您必须等待table中填满值(否则会出现错误)。

To solve that it's just necessary to put another condition on first useEffect ( table.length > 0 ), and load data on second useEffect .要解决这个问题,只需要在第一个useEffect ( table.length > 0 ) 上加上另一个条件,然后在第二个useEffect上加载数据。

So the first useEffect becomes:所以第一个useEffect变成了:

  const interval = useRef(null);
  useEffect(() => {
    if (!interval.current && table.length > 0) {
      interval.current = setInterval(() => {
        const result = _.sample(table);
        console.log(result.label);
      }, 3000);
    }
  }, [table]);

And the second one:第二个:

  useEffect(() => {
    jsonbin.get("/b/5f3d58e44d93991036184474/5")
     .then(({data}) => setTable(data));

    return () => {
      clearInterval(interval.current);
      interval.current = null;
    };
  }, []);

Here the codesandbox updated. 这里更新了codesandbox。

The problem is that you access table before it is loaded.问题是您在加载表之前访问table

You should either provide an initial value to that allows a successful do all your operations:您应该提供一个允许成功执行所有操作的初始值:

// use an array that has at least one element and a label as initial table value
const [table, setTable] = useState([{label: "default label"}]);

useEffect(() => {
  jsonbin.get("/b/5f3d58e44d93991036184474/5")
         .then(({data}) => setTable(data));
});

const result = _.sample(table);
console.log(result.label);

// ...

Or use an if or something alike to handle multiple scenarios:或者使用if或类似的东西来处理多个场景:

// use an empty array as initial table value
const [table, setTable] = useState([]);

useEffect(() => {
  jsonbin.get("/b/5f3d58e44d93991036184474/5")
         .then(({data}) => setTable(data));
});

const result = _.sample(table);
// account for the initial empty table value by checking the result
// of _.sample which is `undefined` for empty arrays
if (result) {
  console.log(result.label);
} else {
  console.log("do something else");
}

// ...

If you fetch your data asynchronously you must think about what you want to use while the data is being fetched.如果您异步获取数据,则必须考虑在获取数据时要使用什么。 The minimal thing to do is tell React to not render the component while the data is missing (being fetch).最简单的事情是告诉 React 在数据丢失(正在获取)时不要渲染组件。

const [table, setTable] = useState([]);

useEffect(() => {
  jsonbin.get("/b/5f3d58e44d93991036184474/5")
         .then(({data}) => setTable(data));
});

const result = _.sample(table);
if (!result) return null; // <- don't render if there is no result

console.log(result.label);

// ...

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

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