为什么 useEffect 不改变段落?

时间:2021-03-28 02:44:52

标签: javascript reactjs

我正在研究 React useEffect hook 并尝试在一个简单的示例中使用它。我想让段落显示模态作为仅在模态打开时发生的效果,并在模态关闭时消失。

所以我在 index.js 中只有 View 组件,这就是组件:

import React from 'react';
import Modal from './Modal.js';

const View = () => {
    let [showModal, setModal] = React.useState(false)
        
    React.useEffect(() => {        
        document.getElementById('alerta').innerHTML = 'Showing modal'
        
        return () => {
            document.getElementById('alerta').innerHTML = ''
        }
    }, [showModal])

    return(
        <>
            <button onClick={() => {setModal(!showModal)}}>
                Show modal
            </button>

            <Modal showModal={showModal} setModal={setModal}/>
        
            <p id="alerta" ></p>
        </>
    )
}

export default View;

Modal.js 看起来像这样

import React from 'react';

const Modal = (props) => {
    if(props.showModal){
        return(
            <div>
                <h1>Showing modal</h1>
                <button onClick={() => props.setModal(false)}>Close</button>
            </div>
        )
    }else {
        return null;
    }
}

export default Modal;

如文档中所述,我的效果返回一个应在效果清除时运行的函数,即模态关闭时。我还指定了仅当我的 showModal 状态发生变化时才运行效果。

如果我在我的效果函数中插入一个 console.log(showModal),当模态显示或关闭时,我会看到它的值发生变化,但问题是,段落是一直都在。

为什么会这样?

1 个答案:

答案 0 :(得分:3)

每次效果钩子运行时,都会填充段落:

React.useEffect(() => {
    document.getElementById('alerta').innerHTML = 'Showing modal'

    return () => {
        document.getElementById('alerta').innerHTML = ''
    }
}, [showModal])

每次渲染,如果 showModal 发生变化,无论它变成什么:

  • 之前渲染的清理将运行,清除内容

  • 新渲染的效果将运行,填充内容

所以它看起来总是很拥挤。

正确的做法是将切换逻辑放入 JSX 并使用状态而不是 DOM 方法:

const View = () => {
    let [showModal, setModal] = React.useState(false)
    return(
        <React.Fragment>
            <button onClick={() => {setModal(!showModal)}}>
                Show modal
            </button>

            <div style={{ display: showModal ? 'block' : 'none' }}>modal here...</div>
        
            <p id="alerta">{showModal ? 'Showing modal' : ''}</p>
        </React.Fragment>
    )
}
ReactDOM.render(<View />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>