React开发:SearchBar向Widget1组件传参返回undefined问题排查
问题原因
- 子组件回调顺序错误:SearchBar的
handleSubmit方法中,先执行了父组件传入的search方法,再执行getCountryCall传值,导致search运行时还没拿到输入的国家名称,和你控制台先输出searchundefined、后输出Indiablabla的现象完全对应。 getCountry方法逻辑错误:一是你主动注释了return语句,调用this.getCountry()本身就返回undefined;二是你在search里调用getCountry时没有传入任何参数,就算没注释return也拿不到值;三是getCountry仅做了打印,没有把传入的国家值同步到Widget1的state。- setState异步特性问题:就算你正确给state赋值了,刚执行完
setState就直接读取this.state.country也拿不到最新值,因为React的setState是批量异步更新的。 - render判断逻辑错误:你写的
this.state.post !== []永远为真,因为数组是引用类型,两个不同数组比较地址永远不相等,会导致展示逻辑异常。
解决方法
按以下步骤修改代码即可:
- 修改Widget1的
getCountry方法,拿到子组件传的国家后直接更新state,更新完成后再触发搜索:
getCountry = (country_child) => { console.log(country_child + "blabla"); // 直接更新state,更新完成后调用search this.setState({ country: country_child }, () => { this.search(); }); }
- 调整Widget1的
search方法,删除里面调用getCountry的逻辑,直接用state里的最新值:
search = async () => { // 这里是state更新后的回调执行场景,能拿到最新的country console.log("search" + this.state.country); const url = "https://api.covid19tracking.narrativa.com/api/2021-11-25/country/" + this.state.country; try { if (this.state.country) { const response = await fetch(url); const data = await response.json(); console.log(data.dates["2021-11-25"].countries[this.state.country]); this.setState({ post: data.dates["2021-11-25"].countries[this.state.country], error: "" }) } else { this.setState({ post: [], error: "Please enter a country name" }) } } catch (err) { if (err.response) { console.log(err.response.data); this.setState({ post: [], error: err.response.data.message }); } } }
- 修改SearchBar的
handleSubmit方法,不需要再主动调用search方法,传完国家值父组件会自动触发搜索:
handleSubmit = (e) => { e.preventDefault(); console.log(this.state.inputValue + "lalalalalal"); // 只需要传值即可,父组件更新完state会自行调用search this.props.getCountryCall(this.state.inputValue); }
- 修正Widget1的render判断条件,判断post数组长度即可:
render() { if (this.state.error === "" && this.state.post.length > 0) { return ( <div> <SearchBar search={this.search} getCountryCall={this.getCountry.bind(this)} /> <div className="container"> <article className="NbrCles"> <h2> Chiffres Clés : {this.state.post.name} </h2> <header> <p>Nombre de cas depuis le début de l'épidémie :</p> <p>Nombre de décès depuis le début de l'épidémie :</p> </header> <div className="row"> <p>{this.state.post.today_confirmed}</p> <p>{this.state.post.today_deaths}</p> </div> </article> </div> </div> ); } else { return ( <div> <SearchBar search={this.search} getCountryCall={this.getCountry.bind(this)} /> <div className="error">{this.state.error}</div> </div> ) } }
- 可选配置:如果需要首次加载默认展示法国的数据,在
componentDidMount中直接设置默认国家即可:
componentDidMount() { this.setState({ country: "France" }, () => { this.search(); }) }
内容的提问来源于stack exchange,提问作者420BeginnerDev
相关产品推荐
相关产品推荐

