为什么useEffect挂钩在加载DOM之前运行?

时间:2019-12-10 14:21:26

标签: javascript reactjs

我无法从react的useEffect Hook访问元素。

const Guest = () => {

    useEffect(() => {

        let selectedElement = document.body.querySelectorAll('[contenteditable=true]');
        console.log(selectedElement)

    })

    return (
        <Fragment>
           <div id='guest-editorjs'>
              <Editor
                  tools={{
                     header: Header,
                     list: List,
                     image: Image,
                     delimiter: Delimiter
                  }}
                  holder="guest-editorjs"
                  onChange={(data) => console.log(data)}
                  onReady={() => console.log('Start!')}
                 data={data} />
        </div>
      </Fragment>

}

我正在尝试访问contenteditable=true的元素,并且所有元素都包含在此Editor组件内。

但是,当我运行代码时,控制台输出将返回console.log(selectedElement)(结果:空NodeList),然后从编辑器组件的onReady返回console.log('Start!')

但是useEffect仅在渲染完成后才开始工作,还是在某些时候我错了?

更新:来宾组件首次呈现后,输出为: -空的NodeList [] -开始!

但是,当我重新渲染该组件时,它将返回带有所有必需元素的NodeList。

3 个答案:

答案 0 :(得分:1)

我也遇到了这个问题,我的解决方案是创建将在重新渲染DOM时设置的内部状态,请参见以下代码以了解:

const [rerender, setRerender] = useState(); // or any state
const [afterRender, setAfterRender] = useState();// internal state

// (1)
useEffect(() => {
   if (!afterRender) return;
   // here DOM is loaded and you can query DOM elements
   // then reset
   setAfterRender(false);
}, [afterRender]);

useEffect(() => {
   setAfterRender(true); // (1) will be called after DOM rendered
}, [rerender]); // or don't set any if you want to listen to all re-render events

return {
  setRerender, // expose function trigger re-render data
}

答案 1 :(得分:0)

如果您需要访问DOM,则可以改用chartView.legend.textColor = UIColor.red

https://reactjs.org/docs/hooks-reference.html#uselayouteffect

答案 2 :(得分:0)

2021 年更新(React 版本 17.0.2)

useEffect 将在 DOM 加载和 UI 绘制之后运行(只是 useLayoutEffect 在 UI 绘制之前运行)。

按顺序运行:

  1. DOM 操作。
  2. useLayoutEffect
  3. 界面绘制
  4. useEffect

它适用于 componentDidMount 和 componentDidUpdate 生命周期。