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

React Route组件不渲染问题:宝可梦搜索跳转后路由无响应

问题根因梳理

  • 缺失根路径路由定义:当前只有/pokemon/:pokemon路径会渲染Search组件,用户首次打开应用访问根路径/时,没有任何组件渲染,看不到搜索入口
  • 结构逻辑错误:将表单嵌套在Link组件内,点击提交按钮会同时触发表单提交事件和Link跳转,两者逻辑冲突
  • 跳转路径不匹配:Link的to属性写的是相对路径pokemon/${this.state.pokemon},跳转后实际路径会变成/pokemon/pokemon/xxx,和你定义的路由规则不匹配
  • 方法定义位置错误:将接口请求方法getPokemon写在render函数内,每次组件渲染都会重复定义该方法,且路由参数变化时无法自动触发数据请求
  • 缺少参数监听逻辑:路由传入的宝可梦参数存在props.match.params.pokemon中,当前没有监听该参数变化触发数据查询的逻辑,也没有搜索结果的展示代码

修改方案

1. 修改Welcome组件

新增根路径路由,保证用户打开首页就能看到搜索框:

import React from 'react';
import {HashRouter as Router, Route, Switch} from 'react-router-dom';
import Search from '../UI/Search'
import './Welcome.css';

let Welcome = (props) => {
    return (
        <Router>
        <div className="welcome-wrapper">
            <h1 className="heading">Welcome to the <b>Pokedex.</b></h1>
            <div>
                <p className="intro">The comprehensive database of Pokemon from the original Blue and Red version.</p>
                <p className="description">Find your favourite and check out their stats</p>
                <Switch>
                    <Route exact path="/" component={Search} />
                    <Route exact path="/pokemon/:pokemon" component={Search} />
                </Switch>
            </div>
        </div>
        </Router>
    );
}

export default Welcome;

2. 修改Search组件

调整结构、方法位置和参数监听逻辑,补充结果展示:

import React, {Component} from 'react';
import axios from 'axios';
import './Search.css';
import SearchButton from './SearchButton';
import {colours} from '../../assets/coloursData';


class Search extends Component {
    state = {
        name: "",
        coloursData: [colours],
        imageUrl: "",
        pokemon: "",
        types: [],
        abilities: [],
        stats: {
            hp: "",
            attack: "",
            defense: "",
            specialAttack: "",
            specialDefense: "",
            speed: "",
        },
        display: false,
    }

    componentDidMount() {
        // 组件挂载时判断是否有路由参数,有则直接查询
        const { pokemon } = this.props.match.params;
        if (pokemon) {
            this.setState({ pokemon }, () => {
                this.getPokemon();
            })
        }
    }

    componentDidUpdate(prevProps) {
        // 路由参数变化时触发查询
        const prevPokemon = prevProps.match.params.pokemon;
        const currentPokemon = this.props.match.params.pokemon;
        if (currentPokemon && prevPokemon !== currentPokemon) {
            this.setState({ pokemon: currentPokemon }, () => {
                this.getPokemon();
            })
        }
    }
    
    getPokemon = async () => {
        try {
            const url = `https://pokeapi.co/api/v2/pokemon/${this.state.pokemon}`
            const res = await axios.get(url)
            const name = res.data.name;
            const imageUrl = res.data.sprites.front_default;
            const types = res.data.types.map(type => type.type.name)
            const abilities = res.data.abilities.map(ability => {
                return ability.ability.name.toLowerCase()
                .split('-')
                .map(s => s.charAt(0).toUpperCase() + s.substring(1)).join(' ')
            }).join(', ');
            let hp, attack, defense, specialAttack, specialDefense, speed;
            res.data.stats.forEach(stat => {
                switch(stat.stat.name) {
                    case 'hp':
                        hp = stat['base_stat']
                        break;
                    case 'attack':
                        attack = stat['base_stat']
                        break;
                    case 'defense':
                        defense = stat['base_stat']
                        break;
                    case 'special-attack':
                        specialAttack = stat['base_stat']
                        break;
                    case 'special-defense':
                        specialDefense = stat['base_stat']
                        break;
                    case 'speed':
                        speed = stat['base_stat']
                        break;
                }
            });
            this.setState({
                name,
                imageUrl,
                types,
                abilities,
                stats: { hp, attack, defense, specialAttack, specialDefense, speed },
                display: true
            })
        } catch (error) {
            console.log(error)
        }
    }

    handleSubmit = (e) => {
        e.preventDefault()
        // 提交后用编程式导航跳转,避免和表单冲突
        this.props.history.push(`/pokemon/${this.state.pokemon}`)
    }

    handleChange = (e) => {
        this.setState({pokemon: e.target.value})
    }
    
    render() {
        return(
            <div>
                {/* 始终显示搜索框 */}
                <form onSubmit= {this.handleSubmit}>
                    <label>
                        <input type="text" placeholder="Search Pokemon" onChange={this.handleChange} value={this.state.pokemon} />
                    </label>
                    <SearchButton></SearchButton>
                </form>

                {/* 查询成功后展示宝可梦信息 */}
                {this.state.display && (
                    <div className="pokemon-card">
                        <h2>{this.state.name}</h2>
                        <img src={this.state.imageUrl} alt={this.state.name} />
                        <p>属性:{this.state.types.join('、')}</p>
                        <p>特性:{this.state.abilities}</p>
                        <div className="stats">
                            <p>HP:{this.state.stats.hp}</p>
                            <p>攻击:{this.state.stats.attack}</p>
                            <p>防御:{this.state.stats.defense}</p>
                            <p>特攻:{this.state.stats.specialAttack}</p>
                            <p>特防:{this.state.stats.specialDefense}</p>
                            <p>速度:{this.state.stats.speed}</p>
                        </div>
                    </div>
                )}
            </div>
            )
    }
        
}
export default Search;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 16:45:04