简体   繁体   English

为什么即使定义了文档,在 Next.js 中使用 getElementById 找到的元素也会返回 null?

[英]Why is an element found using getElementById in Next.js returning null even when document is defined?

Using SSR in my React/Next app.在我的 React/Next 应用程序中使用 SSR。

Trying to find an element with the id but is returning null尝试查找具有 id 但返回 null 的元素

even when document is present (and I can see the div with the id plTable),即使存在文档(我可以看到带有 id plTable 的 div),

and even when getElementById is called after 6 seconds to ensure the element has been loaded on screen.甚至在 6 秒后调用 getElementById 以确保元素已加载到屏幕上。

What is the issue and how can I fix this?问题是什么,我该如何解决?

Here is the component:这是组件:

const LineItemTable: React.FC<LineItemTableProps> = ({ reportName }) => {
  const classes = useStyles({});
  const dispatch = useDispatch();
  const [page, setPage] = useState<number>(0);

  const selectedCompanyId = useSelector((state) => state.company.selectedId);
  const company = useSelector((state) => state.company.current);

  useEffect(() => {
    if (reportName && selectedCompanyId) {
      dispatch(
        getReportByName({
          name: reportName, // 'profit and loss' or 'balance sheet'
          includeLineItems: true,
          page: page,
        }),
      );
    }
  }, [reportName, selectedCompanyId]);

  let plTable: any = 'kk';

  useEffect(() => {
    console.log('uef');
    if (typeof document !== 'undefined') {
      setTimeout(() => {
        plTable = document.querySelector('plTable');// ***** NEVER FOUND ******
        console.log('doc', document); // ***** is found and defined correctly *****
        console.log('plTable', plTable); // ***** null *****
      }, 6000);
    }
  });

  const endObserver = new IntersectionObserver(
    (entries) => {
      const [entry] = entries;
      if (!entry.isIntersecting) {
        //Put what you want to happen if the end is NOT visible
        console.log('not visible');
      } else {
        //Put what you want to happen if the end is visible
        //For instance firing your function
        // setPage(page + 1);
        console.log('visible');
      }
    },
    { root: null, threshold: 1 },
  );
  // endObserver.observe(plTable);

  const getLineItems = useMemo(() => makeGetAllLineItemsByReport(reportName), [
    reportName,
  ]);

  const lineItems = useSelector((state) => getLineItems(state));

  if (!lineItems) return null;

  // ADDED
  // Add an elemnt in your html with the class of "end" at the end of the chart
  // I recommend adding an empty div with the class of "end" and setting it's opacity to 0

  return (
    <div
      id="plTable" // ****** Defined here *******
      style={{
        display: 'flex',
        alignItems: 'flex-end',
        margin: 'auto 0px',
      }}
    >
      <Grid container spacing={3}>
        <Grid item xs={12}>
          <Card
            sx={{
              padding: '20px',
            }}
          >
            <CardContent
              sx={{
                alignItems: 'center',
                display: 'flex',
                height: '1000px',
              }}
            >
              <Scrollbar className={classes.scrollBar}>
                <Table className={classes.root}>
                  <TableHead>
                    <TableRow>
                      <th>
                        <TableCell className={classes.headerStyle}>
                          ANALYSIS CATEGORY
                        </TableCell>
                        <TableCell
                          className={classes.headerStyle}
                          sx={{ marginRight: '10px' }}
                        >
                          NAME
                        </TableCell>
                        {company &&
                          company.dates.map((header) => (
                            <TableCell
                              className={classes.headerStyle}
                              sx={{
                                width: '200px !important',
                                marginLeft: '10px',
                              }}
                              key={header}
                            >
                              {header}
                            </TableCell>
                          ))}
                      </th>
                    </TableRow>
                  </TableHead>
                  <TableBody>
             
                    {lineItems.map((lineItem, i) => (
                      <TableRow key={lineItem.id}>
                        <LineItemRow
                          i={i}
                          id={lineItem.id}
                          reportName={reportName}
                          level={lineItem.level}
                        />
                      </TableRow>
                    ))}
             
                  </TableBody>
                </Table>
              </Scrollbar>
            </CardContent>
          </Card>
        </Grid>
      </Grid>
    </div>
  );
};

According to MDN docs, querySelector either takes an element to look for:根据 MDN 文档, querySelector需要一个元素来查找:

querySelector('plTable')
/* Looking for html tag plTable */

or an identifier:或标识符:

querySelector('#plTable')
/* Looking for an element with id of plTable */

Don't use DOM selectors in React, use refs to access DOM nodes.不要在 React 中使用 DOM 选择器,使用refs访问 DOM 节点。 You can create a ref with useRef or React.createRef or you can pass a callback to the ref attribute of an element, that will receive the DOM node reference when the virtual DOM has done with the reconciliation.您可以使用useRefReact.createRef创建一个 ref,或者您可以将回调传递给元素的ref属性,当虚拟 DOM 完成协调后,它将接收 DOM 节点引用。

To check if the node is mounted and do something with it being sure it is mounted, try this:要检查节点是否已挂载并对其执行某些操作以确保已挂载,请尝试以下操作:

 <div
      id="plTable" // ****** Defined here *******
      style={{
        display: 'flex',
        alignItems: 'flex-end',
        margin: 'auto 0px',
      }}
      ref={node => {
        if (node) console.log("p1Table", node)
        //Do something with node
      }}
 >

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

相关问题 当存在具有该 ID 的元素时,为什么 document.getElementById() 返回 null? - Why is document.getElementById() returning null when there is an element with that Id? Next.js 与 document.getElementById 的问题 - Next.js trouble with document.getElementById 在 Next.js 中导入模块时出现“窗口未定义”或“文档未定义” - "window not defined" or "document not defined" when importing module in Next.js 为什么 document.getElementById() 在 React 中返回 null 尽管 React 中有元素? - Why is document.getElementById() returning null in React although element is there in React? 无法使用document.getElementById获取元素,返回null - not able to get an element using the document.getElementById, returning null Next.js 即使使用 useEffect 也未定义 localStorage - Next.js localStorage not defined even using useEffect 如果未定义元素,document.getelementbyId将返回null? - document.getelementbyId will return null if element is not defined? 为什么document.getElementById返回空值? - Why is document.getElementById returning a null value? document.getElementById即使创建后也返回null - document.getElementById is returning null even after being created 即使在 useEffect 中也没有定义带有 next.js window 的 P5js - P5js with next.js window is not defined even in useEffect
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM