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

如何点击列表中Game元素时单独控制对应div的显示与隐藏?

解决方法

你的问题在于当前Redux里的isDivOpen是全局单一状态,所有Game组件共享同一个值,所以点击一个会影响全部。要实现单个Game独立控制展开状态,需要把状态和每个Game的ID绑定,下面提供两种可行方案:

方案一:给每个Game对象添加独立的展开状态

这种方案直接在每个Game数据里维护isDivOpen字段,适合不需要分离状态和业务数据的场景。

修改Redux切片

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';

const initialState = {
  games: [],
  isLoading: false,
};

// 假设你有获取游戏列表的异步action,返回后给每个游戏初始化isDivOpen
export const fetchGames = createAsyncThunk(
  'games/fetchGames',
  async () => {
    const response = await axios.get('你的游戏列表接口');
    // 给每个游戏添加初始展开状态
    return response.data.map(game => ({ ...game, isDivOpen: true }));
  }
);

export const gameSlice = createSlice({
  name: 'games',
  initialState,
  reducers: {
    toggleSeeMore(state, action) {
      const gameId = action.payload;
      // 找到对应ID的游戏,切换它的isDivOpen状态
      const targetGame = state.games.find(game => game._id === gameId);
      if (targetGame) {
        targetGame.isDivOpen = !targetGame.isDivOpen;
      }
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchGames.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(fetchGames.fulfilled, (state, action) => {
        state.isLoading = false;
        state.games = action.payload;
      });
  },
})

export const { toggleSeeMore } = gameSlice.actions;
export default gameSlice.reducer;

修改Game组件

import React from 'react';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import '../../styles/components/Games/Game.css';
import { useSelector, useDispatch  } from 'react-redux';
import { toggleSeeMore } from '../../slices/gameSlice';

function Game({ game }) {
  const { name, description, employees, hours, photo, _id } = game;
  // 根据当前游戏ID获取对应的展开状态
  const isDivOpen = useSelector(state => 
    state.games.find(g => g._id === _id)?.isDivOpen ?? true
  );
  
  const dispatch = useDispatch()

  const toggleMenu = () => {
    dispatch(toggleSeeMore(_id))
  }

  // 注意:你代码里的formattedTimes需要提前定义,这里保留原结构
  return (
    <div className='game_card'>
      <div className="game_heading">
        <div className="image_container">
          <img src={`http://localhost:5000/uploads/${photo}`} alt="no photo" />
        </div>
        <h1>{name}</h1>
      </div>
      <div className="game_content">
        <p className="description">{description}</p>
        <div className="game_hours">
          {formattedTimes.map((time, index) => (
            <div key={index}>{time}</div>
          ))}
        </div>
      </div>
      <button onClick={toggleMenu}>See More<ExpandMoreIcon/></button>
      <div className={`employees ${isDivOpen ? 'show' : 'hide'}`}>
        <p>Employees</p>
        {employees.map((employee, index) => (
          <div key={index}>{employee}</div>
        ))}
      </div>
    </div>
  );
}

export default Game;

方案二:单独维护展开状态映射表

这种方案把展开状态和游戏数据分离,用一个对象记录每个游戏ID对应的展开状态,更适合需要独立管理UI状态的场景。

修改Redux切片

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';

const initialState = {
  games: [],
  isLoading: false,
  expandedGames: {}, // 结构:{ [gameId]: boolean }
};

export const fetchGames = createAsyncThunk(
  'games/fetchGames',
  async () => {
    const response = await axios.get('你的游戏列表接口');
    return response.data;
  }
);

export const gameSlice = createSlice({
  name: 'games',
  initialState,
  reducers: {
    toggleSeeMore(state, action) {
      const gameId = action.payload;
      // 切换对应ID的展开状态,未记录时默认展开(true)
      state.expandedGames[gameId] = !state.expandedGames[gameId] ?? true;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchGames.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(fetchGames.fulfilled, (state, action) => {
        state.isLoading = false;
        state.games = action.payload;
      });
  },
})

export const { toggleSeeMore } = gameSlice.actions;
export default gameSlice.reducer;

修改Game组件

import React from 'react';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import '../../styles/components/Games/Game.css';
import { useSelector, useDispatch  } from 'react-redux';
import { toggleSeeMore } from '../../slices/gameSlice';

function Game({ game }) {
  const { name, description, employees, hours, photo, _id } = game;
  // 从expandedGames映射表中获取当前游戏的展开状态,默认展开
  const isDivOpen = useSelector(state => 
    state.games.expandedGames[_id] ?? true
  );
  
  const dispatch = useDispatch()

  const toggleMenu = () => {
    dispatch(toggleSeeMore(_id))
  }

  // 注意:你代码里的formattedTimes需要提前定义,这里保留原结构
  return (
    <div className='game_card'>
      <div className="game_heading">
        <div className="image_container">
          <img src={`http://localhost:5000/uploads/${photo}`} alt="no photo" />
        </div>
        <h1>{name}</h1>
      </div>
      <div className="game_content">
        <p className="description">{description}</p>
        <div className="game_hours">
          {formattedTimes.map((time, index) => (
            <div key={index}>{time}</div>
          ))}
        </div>
      </div>
      <button onClick={toggleMenu}>See More<ExpandMoreIcon/></button>
      <div className={`employees ${isDivOpen ? 'show' : 'hide'}`}>
        <p>Employees</p>
        {employees.map((employee, index) => (
          <div key={index}>{employee}</div>
        ))}
      </div>
    </div>
  );
}

export default Game;

两种方案都能实现单个Game独立控制展开状态,你可以根据自己的业务场景选择。

内容的提问来源于stack exchange,提问作者tukitooo1998

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:35:00