React中无需useEffect控制react-bootstrap Toast显示状态的可行性咨询
结论
- 你原来用
useEffect监听items修改show的写法确实冗余,还会带来额外的重渲染开销,完全没有必要。 - 直接写
const show = items.length > 0是否可行,取决于你的业务需求:
场景1:仅在首次拿到非空数据时触发Toast,支持手动关闭/自动隐藏后不再弹出
这种场景下show需要独立状态,因为存在和items无关的手动修改逻辑,但不需要单独写useEffect监听items,直接在请求拿到结果的回调里控制显示即可,优化后代码如下:
import "./styles.css"; import React, { useState, useEffect } from "react"; import { Toast } from "react-bootstrap"; export default function App() { const [error, setError] = useState(null); const [show, setShow] = useState(false); const [items, setItems] = useState([]); useEffect(() => { fetch("https://api.example.com/items") .then((res) => res.json()) .then( (result) => { setItems(result); // 拿到结果后直接判断是否要显示Toast,无需额外useEffect if (result.length > 0) { setShow(true); } }, (error) => { setError(error); } ); }, []); const toggleShowB = () => setShow(!show); return ( <div className="App"> <Toast onClose={() => setShow(false)} show={show} delay={3000} autohide> <Toast.Header /> <Toast.Body>Woohoo, you're reading this text in a Toast!</Toast.Body> </Toast> </div> ); }
原来的useEffect写法还有隐性bug:如果用户手动关闭Toast后items没有变化,下一次组件重渲染时useEffect会再次把show设为true,导致Toast重复弹出,优化后的写法可以避免这个问题。
场景2:只要items非空就必须显示Toast,不需要保留手动关闭状态
这种场景下show完全是items的派生值,不需要单独存为状态,直接写派生值即可,代码可以简化为:
import "./styles.css"; import React, { useState, useEffect } from "react"; import { Toast } from "react-bootstrap"; export default function App() { const [error, setError] = useState(null); const [items, setItems] = useState([]); useEffect(() => { fetch("https://api.example.com/items") .then((res) => res.json()) .then( (result) => { setItems(result); }, (error) => { setError(error); } ); }, []); // 直接派生show状态,无需useState和useEffect const show = items.length > 0; return ( <div className="App"> <Toast onClose={() => {}} show={show} delay={3000} autohide> <Toast.Header /> <Toast.Body>Woohoo, you're reading this text in a Toast!</Toast.Body> </Toast> </div> ); }
这种写法没有多余的状态和副作用,性能最优。
内容的提问来源于stack exchange,提问作者jacobcan118
相关产品推荐
相关产品推荐

