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

React遍历渲染产品时,点击如何仅展示对应产品的详情?

问题根源

当前全局Context里的detailsForProduct是单一变量,所有Product组件共用这个值。点击任意产品后,全局状态更新,所有组件都会读取同一个详情数据,导致全部产品显示相同内容。

解决方案

核心思路是让全局状态按产品维度存储详情和加载状态,每个Product组件只读取自身对应产品的数据。

1. 更新Context的状态结构

修改Context的初始状态,用对象分别存储每个产品的详情和加载状态:

// 假设这是你的SearchContext初始状态
const initialState = {
  detailsMap: {}, // key: 产品唯一标识(name或_id), value: 对应详情
  fetchingMap: {} // key: 产品唯一标识, value: 是否正在加载
};

2. 修改fetchDetailsForProduct方法

更新Context里的请求逻辑,针对单个产品维护状态:

// 示例reducer逻辑(根据你的实际Context实现调整)
const reducer = (state, action) => {
  switch (action.type) {
    case 'FETCH_DETAILS_START':
      return {
        ...state,
        fetchingMap: {
          ...state.fetchingMap,
          [action.payload.productId]: true
        }
      };
    case 'FETCH_DETAILS_SUCCESS':
      return {
        ...state,
        fetchingMap: {
          ...state.fetchingMap,
          [action.payload.productId]: false
        },
        detailsMap: {
          ...state.detailsMap,
          [action.payload.productId]: action.payload.details
        }
      };
    case 'FETCH_DETAILS_ERROR':
      return {
        ...state,
        fetchingMap: {
          ...state.fetchingMap,
          [action.payload.productId]: false
        }
      };
    default:
      return state;
  }
};

// 对应的fetchDetailsForProduct方法
const fetchDetailsForProduct = async (product) => {
  const productId = product._id; // 用_id作为唯一标识更可靠
  dispatch({ type: 'FETCH_DETAILS_START', payload: { productId } });
  try {
    const response = await apiCallToGetDetails(product); // 替换成你的API请求
    dispatch({ 
      type: 'FETCH_DETAILS_SUCCESS', 
      payload: { productId, details: response.data } 
    });
  } catch (error) {
    dispatch({ type: 'FETCH_DETAILS_ERROR', payload: { productId } });
  }
};

3. 修改App组件

传递当前产品对应的详情和加载状态给Product组件:

const App = () => {
  const { state: { detailsMap, fetchingMap }, fetchDetailsForProduct } = useContext(SearchContext);
  
  const getDetails = async (product) => {
    await fetchDetailsForProduct(product);
  };
  
  return (
    <FlatList
      data={data}
      renderItem={({ item }) => {
        const productId = item._id;
        return (
          <Product
            product={item}
            getDetails={getDetails}
            details={detailsMap[productId]}
            isFetching={fetchingMap[productId] || false}
          />
        );
      }}
      keyExtractor={item => item._id}
    />
  );
};

4. 调整Product组件逻辑

确保只渲染当前产品的详情,同时优化请求逻辑(已加载过则不再重复请求):

const Product = ({ getDetails, product, details, isFetching }) => {
  const [expanded, setExpanded] = useState(false);
  const productId = product._id;

  const handlePress = async () => {
    const newExpanded = !expanded;
    setExpanded(newExpanded);
    // 展开且未加载过详情时才发起请求
    if (newExpanded && !details) {
      await getDetails(product);
    }
  };

  return (
    <>
      <ListItem.Accordion
        content={
          <>
            <ListItem>
              <View>
                <Text>{product.name}</Text>
              </View>
            </ListItem>
          </>
        }
        isExpanded={expanded}
        onPress={handlePress}
      >
        <Details
          isFetching={isFetching}
          details={details}
        />
      </ListItem.Accordion>
    </>
  );
};
额外优化建议
  • 始终用产品的_id作为唯一标识,避免同名产品导致的数据混乱
  • 可在Context中添加缓存过期逻辑,防止长期存储无效数据
  • 补充错误状态处理,给用户展示加载失败的提示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 03:47:51