You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 05:15:40