开发者问题收集

使用 lodash 和 setInterval 的 React 问题

2020-08-20
255

我在使用 Lodash + setInterval 时遇到问题。

我想要做的: 每 3 秒随机检索我的对象的一个​​元素

这是我的对象:

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

所以我从这个开始:

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

控制台给出 => Object { label: "Figue", labelEn: "fig" }

但是如果添加:

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

控制台给出 => TypeError: 结果未定义

除此之外,我尝试添加 setInterval 并尝试使用 useEffect 但代码崩溃或控制台每 3 秒给我两个数字 => 2,6,2,6 ......

2个回答

你好,假设 table 对象已正确填充,您可以使用 lodashsetInterval 获取 table 的随机对象,使用 useEffectuseRef 钩子,例如:

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

然后,要在卸载组件时清理 setInterval ,您可以使用另一个 useEffect ,方式如下:

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

编辑

经过您的解释,我找到了问题的原因。在启动 setInterval 之前,您必须等待 table 已填充值(否则会出错)。

要解决这个问题,只需在第一个 useEffect 上添加另一个条件( table.length > 0 ),然后在第二个 useEffect 上加载数据。

因此,第一个 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]);

第二个为:

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

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

这里 codesandbox 已更新。

Giovanni Esposito
2020-08-20

问题是您在加载 table 之前访问它。

您应该提供一个初始值,以便成功执行所有操作:

// 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);

// ...

或者使用 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");
}

// ...

如果您异步获取数据,则必须考虑在获取数据时要使用什么。要做的最少的事情是告诉 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);

// ...
3limin4t0r
2020-08-20