reactjs 在useEffect中获取以创建组件

omvjsjqw  于 2023-03-08  发布在  React
关注(0)|答案(2)|浏览(92)

我将如何使用useEffect创建一个组件?

useEffect(() => {
      fetch('https://website')
         .then((res) => res.json())
         .then((data) => {
            setData(data)

            // Use fetched data to create object "roles"

            let cards = roles.map((path) => (
               <Box m="sm" pt="xl">
                  <Card key={path.id} p="lg" radius="md href="#"
                     onClick={ () => handlePopup(path.role) }>
                  </Card>
               </Box>
            ));
      })
}

return (
    <>
       {cards} // this doesn't work.
    </>

)

当前代码不起作用。“卡”没有加载,只是得到一个空白区域。我把它都保留在获取中,因为数据是相关的,我不知道如何分割它。不知道是否有一个更聪明的方法。

qvsjd97n

qvsjd97n1#

您可以在useEffect之外Map状态变量

useEffect(() => {
  fetch('https://website')
    .then((res) => res.json())
    .then((data) => {
      setData(data)
    })
}

return (
  <>
    {data.roles.map((path, i) => (
      <Box key={i} m="sm" pt="xl">
        <Card key={path.id} p="lg" radius="md href="#"
          onClick={ () => handlePopup(path.role) }>
        </Card>
      </Box>
    ));}
  </>
)

如果要将它们存储在单独的变量中,可以在useEffect之外对其进行设置,以便可以访问它。

useEffect(() => {
  fetch('https://website')
    .then((res) => res.json())
    .then((data) => {
      setData(data)
    })
}

const cards = data.roles.map((path, i) => (
  <Box key={i} m="sm" pt="xl">
    <Card key={path.id} p="lg" radius="md href="#"
      onClick={ () => handlePopup(path.role) }>
    </Card>
  </Box>
));

return (
  <>
    {cards}
  </>
)

正如评论中提到的,Map元素时还需要设置唯一的key

du7egjpx

du7egjpx2#

您应该存储(useState)来自fetch调用的原始JS对象数组(结果),而不是构造呈现的DOM。
key应该出现在Array.prototype.map调用的每个直接元素上。在下面的例子中,<Grid> Package 器接收这个属性。

**注意:**由于与id关联的role可能会随时间而更改,因此id甚至index可能不够唯一。您可以对对象进行哈希以接收真正唯一的ID,或者您可以生成UUID。

const { useCallback, useEffect, useState } = React;
const { Box, Card, CardContent, Container, Grid } = MaterialUI;

// https://stackoverflow.com/a/2117523/1762224
const uuidv4 = () =>
  ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));

const randomUUID = () => {
  try { return crypto.randomUUID(); } // Should be fine...
  catch (e) { console.log('Session is insecure'); return uuidv4(); }
}

const fetchPaths = () => Promise.resolve([
  { id: 1, role: 'admin' },
  { id: 2, role: 'user' }
]);

const App = () => {
  const [paths, setPaths] = useState([]);

  useEffect(() => {
    fetchPaths().then(setPaths); // Store the result
  }, []);

  const handlePopup = useCallback((role) => {
    alert(role);
  }, []);

  return (
    <Container>
      <Grid container spacing={2}>
        {paths.map(path => (
          <Grid key={randomUUID()} item xs={6}>
            <Box m="sm" pt="xl">
              <Card
                p="lg"
                radius="md"
                href="#"
                onClick={() => handlePopup(path.role)}>
                 <CardContent>
                  {path.role}
                 </CardContent>
              </Card>
            </Box>
          </Grid>
        ))}
      </Grid>
    </Container>
  );
};

ReactDOM
  .createRoot(document.getElementById('root'))
  .render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@material-ui/core@4.7.2/umd/material-ui.development.js"></script>

相关问题