我正在研究 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),当模态显示或关闭时,我会看到它的值发生变化,但问题是,段落是一直都在。
为什么会这样?
答案 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>