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

React项目useEffect初始渲染破坏加密货币列表值 该如何解决?

加密货币搜索功能修复方案

问题根因

你的代码存在三个核心问题导致初始渲染无数据:

  • filter方法的回调箭头函数使用了大括号包裹逻辑但没有显式return,导致所有匹配判断都返回undefined,过滤结果为空
  • 组件初始化时接口还在请求中,cryptoList为undefined,useEffect初始执行会将cryptos赋值为undefined
  • useEffect默认会在组件首次渲染后执行一次,也就是你说的初始化执行问题

最优替代实现方案(无需控制useEffect执行)

筛选结果属于基于cryptoList和searchTerm的派生状态,不需要额外存储为state,也不需要useEffect同步,直接在渲染时计算即可,代码更简洁也不会有初始执行问题:

import { Card, Row, Col, Input } from 'antd'
import React from 'react'
import { Link } from 'react-router-dom'
import { useGetCryptosQuery } from '../services/CryptoApi'
import { useState } from 'react'
import millify from 'millify'

const Cryptocurrencies = (props) => {
    const count = props.simplified ? 10 : 100;
    const { data: cryptoList, isFetching } = useGetCryptosQuery(count)
    const [searchTerm, setSearchTerm] = useState('')

    if (isFetching) {
        return "loading...";
    }

    // 直接计算筛选结果,不需要额外state和useEffect
    const filteredCryptos = cryptoList?.data?.coins?.filter(
      coin => coin.name.toLowerCase().includes(searchTerm.toLowerCase())
    ) || []

    return (
        <div>
            <div>
                <Input 
                  placeholder="搜索加密货币" 
                  onChange={(e) => setSearchTerm(e.target.value)} 
                />
            </div>
            <Row gutter={[32, 32]} className="crypto-card-container">
                {filteredCryptos.map((currency) => (
                    <Col xs={24} sm={12} lg={6} className="crypto-card" key={currency.id}>
                        <Link to={`/crypto/${currency.id}`}>
                            <Card
                                title={`${currency.rank}.${currency.name}`}
                                extra={<img className="crypto-image" src={currency.iconUrl} />}
                                hoverable
                            >
                                <p>价格 : ${millify(currency.price)}</p>
                                <p>市值 : {millify(currency.marketCap)}</p>
                                <p>日涨跌幅 : {millify(currency.change)}%</p>
                            </Card>
                        </Link>
                    </Col>
                ))}
            </Row>
        </div>
    )
}

export default Cryptocurrencies

禁止useEffect初始执行的实现方法

如果你坚持要使用useEffect实现该功能,可以通过ref标记首次渲染状态,跳过初始执行逻辑:

  1. 引入useRef创建首次渲染标记
  2. 在useEffect首次执行时修改标记,跳过逻辑,后续依赖变化才执行筛选
  3. 修复原有filter回调的返回值问题
// 新增引入useRef
import { useState, useEffect, useRef } from 'react'

const Cryptocurrencies = (props) => {
    const count = props.simplified ? 10 : 100;
    const { data: cryptoList, isFetching } = useGetCryptosQuery(count)
    const [cryptos, setCryptos] = useState([])
    const [searchTerm, setSearchTerm] = useState('')
    // 首次渲染标记
    const isFirstRender = useRef(true)

    useEffect(() => {
        // 接口还在请求中不执行逻辑
        if (!cryptoList?.data?.coins) return

        // 跳过初始渲染执行
        if (isFirstRender.current) {
            isFirstRender.current = false
            // 初始赋值全量加密货币数据
            setCryptos(cryptoList.data.coins)
            return
        }

        // 修复filter回调的返回逻辑,不用大括号可以隐式return
        const filteredData = cryptoList.data.coins.filter( 
            (coin) => coin.name.toLowerCase().includes(searchTerm.toLowerCase()) 
        )
        setCryptos(filteredData)
    }, [searchTerm, cryptoList])

    // 剩下的渲染逻辑和之前一致,用cryptos.map渲染即可
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 06:57:02