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
相关产品推荐
相关产品推荐

