React+Styled-Components:加减符号切换逻辑生效原因及优化咨询
加减号切换的问题解析
一、现有代码能运行的原因
你当前的代码之所以能实现从「+」到「-」的切换,核心是JS逗号运算符的特性和组件的绝对定位:
- 初始
visability为true时,三元表达式渲染<Vertical />,加上固定存在的<Horizontal />,两个绝对定位的div叠加出「+」号。 - 点击后
visability变为false,三元表达式的else分支是(<Vertical />, <Horizontal />),这里的逗号运算符会执行所有表达式,但只返回最后一个结果(也就是<Horizontal />)。此时<Plus>容器里会有两个<Horizontal />,但因为它们的样式、位置完全一致,视觉上重叠后还是显示一条横线,看起来就是「-」号。
另外注意:你在changeVisability里打印的visability会滞后一次,因为setState是异步的,要看到最新值得用useEffect监听。
二、疑问代码失效的原因
你写的{visability ? (<Vertical />) : ()}里,else分支的()是无效的JSX可渲染内容。React要求条件渲染的分支必须返回null、undefined、false、空字符串或者合法的React元素,空括号()不属于这些范畴,会被React视为无效内容,导致渲染异常。
如果想实现「else时不渲染任何内容」,应该把else分支写成null:
{visability ? <Vertical /> : null}
三、更优的实现方式
方式1:简化条件渲染(最直接)
直接控制<Vertical />的显示/隐藏,去掉多余的<Horizontal />渲染,逻辑更清晰:
function Nav() { const [isPlus, setIsPlus] = useState(true); const toggleIcon = () => setIsPlus(!isPlus); return ( <Button onClick={toggleIcon}> <ListItemsNoRightSpace>More</ListItemsNoRightSpace> <Plus> <Horizontal /> {isPlus && <Vertical />} </Plus> </Button> ); }
方式2:用CSS控制显示(更优雅)
给<Vertical />加条件样式,通过display控制显隐,减少组件的挂载/卸载开销:
// 用内联样式实现 function Nav() { const [isPlus, setIsPlus] = useState(true); const toggleIcon = () => setIsPlus(!isPlus); return ( <Button onClick={toggleIcon}> <ListItemsNoRightSpace>More</ListItemsNoRightSpace> <Plus> <Horizontal /> <Vertical style={{ display: isPlus ? 'block' : 'none' }} /> </Plus> </Button> ); } // 或者用styled-components的条件类 const Vertical = styled.div` position: absolute; left: 14px; top: 9px; width: 2px; height: 12px; background-color: black; display: ${props => props.show ? 'block' : 'none'}; `; // 使用时 <Vertical show={isPlus} />
方式3:封装成独立组件(复用性更高)
把加减号逻辑封装成独立组件,内聚逻辑,方便其他页面复用:
const ToggleIcon = ({ isPlus, onClick }) => ( <Plus> <Horizontal /> {isPlus && <Vertical />} </Plus> ); // 在Nav中使用 function Nav() { const [isPlus, setIsPlus] = useState(true); return ( <Button onClick={() => setIsPlus(!isPlus)}> <ListItemsNoRightSpace>More</ListItemsNoRightSpace> <ToggleIcon isPlus={isPlus} /> </Button> ); }
内容的提问来源于stack exchange,提问作者Niklas
相关产品推荐
相关产品推荐

