useReducer实现toggle功能时如何用三元条件控制Modal背景色
实现方案
你现有代码有3个前置问题需要先修复,再添加背景色判断逻辑:
- reducer里未定义
CLOSE_MODAL的action处理,触发关闭时会直接抛错 - Modal组件没有拿到当前文本展开/收起的状态标识,无法判断背景色
- Modal内的
useEffect没有添加依赖数组,会在每次组件重渲染时重复创建定时器,导致弹窗异常关闭
分步修改说明
1. 补全reducer逻辑,添加关闭弹窗的状态处理
在reducer的switch里新增CLOSE_MODAL分支,触发时把isModalOpen设为false即可。
2. 给Modal透传readMore2状态
渲染Modal组件时,把全局state里的readMore2作为prop传入,供组件内部判断状态。
3. 修复useEffect定时器问题
给useEffect添加空依赖数组,保证弹窗挂载时只启动1次2秒定时器,同时新增清理函数,组件卸载时清除定时器避免内存泄漏。
4. 用三元表达式动态控制Modal背景色
在Modal的容器元素上,通过readMore2的布尔值判断:值为true(文本展开)时背景设为绿色,值为false(文本收起)时背景设为红色。
5. 添加侧边滑入样式
给Modal容器加基础定位和transition动画,实现滑入效果。
修改后完整代码
import React, { useReducer, useEffect } from 'react'; // 这里替换为你项目中实际的Text2文本常量 const Text2 = '替换为你原本的5句完整文本内容'; const reducer = (state, action) => { switch(action.type) { case 'TEXT2': return { ...state, readMore2: !state.readMore2, isModalOpen : true, modalContent: 'Toggle Text' } // 新增关闭弹窗的action处理 case 'CLOSE_MODAL': return { ...state, isModalOpen: false } default: throw new Error ('error') } } const stateDefault = { readMore2 : false, isModalOpen: false, // 补全弹窗初始关闭状态 modalContent:'' } function About() { return ( <> <AboutText/> </> ) } const AboutText = () => { const [state, dispatch] = useReducer(reducer, stateDefault) const closeModal = () => { dispatch({type:'CLOSE_MODAL'}) } return ( <> <article> <p className="p2"> {!state.readMore2 ? `${Text2.substring(0,45)} ...` : Text2 } { state.isModalOpen && <Modal closeModal={closeModal} modalContent= {state.modalContent} // 将展开状态透传给Modal组件 isReadMore={state.readMore2} />} <button className='btn2' onClick={()=> dispatch({type:'TEXT2'})} > {!state.readMore2 ? 'Read More' : 'Show Less'} </button> </p><br/> </article> </> ) } const Modal = ({modalContent, closeModal, isReadMore}) => { useEffect(()=> { const timer = setTimeout(() => { closeModal() }, 2000); // 组件卸载时清除定时器,避免内存泄漏和状态异常 return () => clearTimeout(timer); // 空依赖保证弹窗挂载时仅创建一次定时器 }, []) return ( <> {/* 三元判断直接绑定内联样式,也可以绑定不同className */} <div className='modal-box' style={{ // 侧边滑入基础定位样式 position: 'fixed', right: 0, top: '20%', padding: '16px 24px', borderRadius: '4px 0 0 4px', color: '#fff', // 核心三元判断:文本展开状态为绿色,收起状态为红色 backgroundColor: isReadMore ? '#2ecc71' : '#e74c3c', animation: 'slideIn 0.3s ease forwards' }} > <h4 className='modal-text'>{modalContent}</h4> </div> {/* 滑入动画关键帧,也可以抽到全局CSS文件中 */} <style> {` @keyframes slideIn { from { transform: translateX(100%); } to { transform: translateX(0); } } `} </style> </> ) } export default About
如果你不想用内联样式,也可以把背景色判断改成className绑定:
className={modal-box ${isReadMore ? 'modal-green' : 'modal-red'}},然后在对应CSS文件里给modal-green、modal-red两个类分别配置绿色、红色背景即可。
内容的提问来源于stack exchange,提问作者pete
相关产品推荐
相关产品推荐

