React调用PokeAPI获取数据失败:表单提交请求异常排查
问题分析与解决方案
我一眼就看到两个关键问题导致你表单提交时无法获取数据,咱们一个个来解决:
1. 未绑定performSearch方法到组件实例
你在构造函数里注释了this.performSearch = this.performSearch.bind(this);,这会导致在handleSubmit中调用this.performSearch时,this的指向不是你的App组件实例。这样一来,performSearch里的this.setState就会报错,甚至整个函数的执行都会出问题。
解决方法:取消构造函数里那行的注释,把performSearch绑定到组件:
constructor(props) { super(props); this.state = { rows: [], value: "" }; this.searchChangeHandler = this.searchChangeHandler.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.performSearch = this.performSearch.bind(this); // 取消这行注释 //this.performSearch("water") }
2. 表单提交的默认行为会刷新页面
当你点击提交按钮时,浏览器会默认刷新页面,这会导致你的组件重新初始化,之前的异步请求即使已经发送,结果也会因为页面刷新而丢失,所以你看不到任何数据。
解决方法:在handleSubmit里调用event.preventDefault()阻止默认行为:
handleSubmit(event) { event.preventDefault(); // 添加这行 alert('A pokemon type was submitted: ' + this.state.value); console.log(this.state.value); this.performSearch(this.state.value); }
额外优化建议(可选)
还有一个小问题:你在嵌套的ajax请求里每次push一个PokemonRow就调用setState,这样会导致组件频繁重渲染。而且pokemonRows是var声明的,在异步请求中可能会有闭包问题。可以改成用Promise.all来处理所有单个宝可梦的请求,然后一次性更新状态:
performSearch(searchTerm) { const urlString = "http://pokeapi.salestock.net/api/v2/type/" + searchTerm + "/"; alert(urlString); $.ajax({ url: urlString, success: (searchResults) => { console.log("Fetched Data Succesfully"); console.log(searchResults); const pokemonOfType = searchResults.pokemon; // 把所有单个宝可梦的请求变成Promise数组 const pokemonPromises = pokemonOfType.map(pokemon => { return new Promise((resolve, reject) => { $.ajax({ url: pokemon.pokemon.url, success: resolve, error: reject }); }); }); // 等待所有请求完成 Promise.all(pokemonPromises) .then(pokemonList => { const pokemonRows = pokemonList.map(pokemon => ( <PokemonRow key={pokemon.id} pokemon={pokemon} /> )); this.setState({ rows: pokemonRows }); console.log("this.state.rows.length: " + this.state.rows.length); }) .catch(err => { console.error("Failed to fetch individual pokemon data"); alert("Failed to fetch individual pokemon data"); }); }, error: (xhr, status, err) => { console.error("Failed to fetch data"); alert("Failed to fetch data, urlString: " + urlString); } }); }
这样修改后,你的表单提交应该就能正常获取并展示宝可梦数据了!
内容的提问来源于stack exchange,提问作者khanvict
相关产品推荐
相关产品推荐

