React添加textarea样式后深色模式无法切回浅色模式的问题
React组件模式切换无法切回浅色模式的原因及修复
问题核心
在switchMode函数中添加修改textarea样式的代码后,无法从深色模式切换回浅色模式,移除该代码后功能恢复正常。
问题原因分析
mode变量未使用React状态管理
你用let mode = "light"定义的是普通变量,而非React状态。每次组件重渲染(比如调用textAreaStyleFinal更新样式状态时),这个变量都会被重新初始化为"light"。导致第一次切换到深色模式后,组件重渲染,mode又变回"light",下次点击切换时,逻辑会再次执行深色模式的代码,永远无法进入else分支。状态变量命名混淆(次要但需修正)
const [textAreaStyleInitial, textAreaStyleFinal] = useState(...)的命名颠倒了React状态的解构规则:第一个值是当前状态,第二个是更新状态的函数。这种命名不仅可读性极差,还容易引发后续维护错误。
修复方案
修复后的完整代码
import React, { useState } from "react"; export default function TextForm(props) { const handleUpClick = () => { const newText = text.toUpperCase(); setText(newText); }; const handleDownClick = () => { const newText = text.toLowerCase(); setText(newText); }; const handleClearClick = () => { setText(""); }; const handleReverseClick = () => { setText(text.split(" ").reverse().join(" ")); }; const handleOnChange = (Event) => { setText(Event.target.value); }; // 用useState管理mode状态,确保组件重渲染时状态不丢失 const [mode, setMode] = useState("light"); const switchMode = () => { if (mode === "light") { document.body.style.backgroundColor = "black"; document.body.style.color = "white"; setMode("dark"); setTextAreaStyle({ backgroundColor: "darkgrey", color: "darkblue", }); } else { document.body.style.backgroundColor = "white"; document.body.style.color = "black"; setMode("light"); setTextAreaStyle({ backgroundColor: "white", color: "black", }); } }; const [text, setText] = useState(""); // 修正状态命名,符合React规范 const [textAreaStyle, setTextAreaStyle] = useState({ backgroundColor: "white", color: "black", }); return ( <> <div className="container"> <h1>{props.heading}</h1> <div className="mb-3"> <textarea className="form-control" id="exampleFormControlTextarea1" rows="3" placeholder="Enter Your Text Here" value={text} onChange={handleOnChange} style={textAreaStyle} ></textarea> </div> <button className="btn btn-primary mx-1" onClick={handleUpClick}> Convert to Uppercase </button> <button className="btn btn-primary mx-1" onClick={handleDownClick}> Convert to Lowercase </button> <button className="btn btn-primary mx-1" onClick={handleReverseClick}> Reverse Sentence </button> <button className="btn btn-primary mx-1" onClick={handleClearClick}> Clear All </button> </div> <div className="container my-3"> <div className="form-check form-switch my-3"> <label className="form-check-label" htmlFor="flexSwitchCheckDefault"> Enable Dark Mode </label> <input className="form-check-input" type="checkbox" role="switch" id="flexSwitchCheckDefault" onChange={switchMode} /> </div> <h2>Your Text Summary</h2> <p> {text.split(" ").filter(word => word.trim() !== "").length} Words and {text.length} characters </p> </div> </> ); }
关键修复点说明
- 将
let mode替换为useState("light"),让React追踪mode状态,确保组件重渲染时不会丢失当前模式值。 - 修正textarea样式的状态命名为
textAreaStyle和setTextAreaStyle,符合React状态的命名规范,避免混淆。 - 额外修复了单词统计的小问题:原代码会把空字符串(比如多个空格)统计为单词,新增
filter(word => word.trim() !== "")过滤无效内容。
内容的提问来源于stack exchange,提问作者Abhinav Basu
相关产品推荐
相关产品推荐

