【发布时间】:2017-05-30 17:23:10
【问题描述】:
我对此感到困惑,我无法弄清楚我做错了什么。我正在尝试做一个维基百科查看器(如Freecodecamp.com 上的解释),基本上是对维基百科文章的简单搜索。
我已经在 HTML/CSS/JS(jQuery) 中完成了它,现在因为我正在学习 React,我正在尝试在 React 中重新创建它。
我已经拆分了我的组件,我正在使用 fetch 使用 Wikipedia API 获取数据,并且所有内容都在呈现,除了搜索结果。我只是无法显示最终结果,这是整个“应用程序”的重点。
使用 React 开发工具,我已经确定正在获取数据并将道具传递给子组件,并且我已经测试了虚拟子组件是否会渲染并且它会渲染,因此渲染所有组件都不是问题,我只是在某处遗漏了一些步骤来让它用所有必要的数据呈现该组件。
所有代码都在this 代码沙箱中。我已经按照我在本地设置的方式进行了设置,这样你就可以清楚地看到我是如何做事的。
感谢任何帮助!
抱歉,问题有点长,包含所有文本和代码。如果这对某些人来说更方便,我还包括了所有按文件拆分的代码。
App.jsx
import React from 'react';
import WikiHeader from './Header';
import WikiSearch from './Search';
import OutputList from './OutputList';
import 'purecss';
import 'purecss/build/grids-responsive-min.css'
import './App.css';
var resultsArray = [];
const wikiAPI = "https://en.wikipedia.org/w/api.php?&";
var wikiHeaders = {
action: "query",
format: "json",
origin: "*",
prop: "info|extracts",
exsentences: 2,
exlimit: 5,
generator: "search",
inprop: "url",
gsrsearch: "",
gsrnamespace: 0,
gsrlimit: 5,
exintro: 1
};
// Format headers to be used for a query string
function toQueryString(obj) {
var parts = [];
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
parts.push(encodeURIComponent(i) + "=" + encodeURIComponent(obj[i]));
}
}
return parts.join("&");
}
class App extends React.Component {
constructor() {
super();
this.state = {
results: []
}
this.ajaxCall = this.ajaxCall.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
// AJAX using fetch
ajaxCall() {
resultsArray = []; // clear array every time ajax is called so that it doesn't just add new items to previous items
toQueryString(wikiHeaders);
fetch(wikiAPI + toQueryString(wikiHeaders)).then(function(response) {
return response.json();
}).then(function(json) {
for (var prop in json.query.pages) {
// push response items to array so that state isn't directly changed (not changing state recommended by Facebook)
resultsArray.push({
title: json.query.pages[prop].title,
url: json.query.pages[prop].fullurl,
extract: json.query.pages[prop].extract
});
}
}).catch(function(ex) {
console.log('Json parsing failed', ex); // show error if JSON parsing fails
});
this.setState({results: resultsArray}); // set state.results to resultsArray
}
handleChange(e) {
wikiHeaders.gsrsearch = e.target.value; // get input value and store it
}
handleSubmit(e) {
e.preventDefault();
console.log("Hey, this is a submit event!"); // show if function is being called
// Call fetch
this.ajaxCall();
// Clear the search box after submit
document.getElementById("search-input").value = "";
}
render() {
return (
<div className="full-wrapper pure-g">
<div className="pure-u-1">
<WikiHeader />
<WikiSearch onChange={this.handleChange} onSubmit={this.handleSubmit} />
<OutputList results={this.state.results} />
</div>
</div>
);
}
}
export default App;
Header.jsx
import React from 'react';
class WikiHeader extends React.Component {
render() {
return (
<h1 className="site-title">Wikipedia Viewer</h1>
);
}
};
export default WikiHeader;
搜索.jsx
import React from 'react';
class WikiSearch extends React.Component {
render() {
return (
<div className="search-input">
<form className="pure-form" onSubmit={this.props.onSubmit}>
<div className="pure-u-1 pure-u-md-3-4">
<input type="text" id="search-input" onChange={this.props.onChange} className="pure-input pure-u-1" placeholder="Input your search term here..."></input>
</div>
<div className="pure-u-1 pure-u-md-1-4 button-wrapper">
<button type="submit" id="search-button" className="pure-button pure-button-primary pure-u-1 pure-u-md-23-24">Search</button>
</div>
</form>
<a href="https://en.wikipedia.org/wiki/Special:Random" alt="Open a Random Wikipedia article" target="_blank" rel="noopener noreferrer">or see a random Wikipedia article</a>
</div>
);
}
};
export default WikiSearch;
输出列表.jsx
import React from 'react';
import OutputItem from './OutputItem';
class OutputList extends React.Component {
render() {
var finalResult = this.props.results.map((result, index) => {
return (
<OutputItem
key={index}
title={result.title}
url={result.url}
extract={result.extract}
/>
);
});
return (
<div id="search-output" className="pure-g">
<ul className="article-list pure-u-1">
{finalResult}
</ul>
</div>
);
}
}
export default OutputList;
OutputItem.jsx
import React from 'react';
class OutputItem extends React.Component {
render() {
return (
<div>
<li className="pure-u-1">
<a href={this.props.url} target="_blank" rel="noopener noreferrer">
<h2>{this.props.title}</h2>
{this.props.extract}
</a>
</li>
</div>
);
}
}
export default OutputItem;
【问题讨论】:
-
在 App.jsx 中,ajax 调用和 setState 方法都是异步的。在进行 ajax 获取时,调用 setState 方法,传入 original 空 resultsArray,因为 ajax 获取尚未完成。将 this.setState 行移动到 ajax fetch 的第一个 'then' 中,就在 for 循环之后。 'this' 将不再被定义,所以只需将 then 中的函数更改为箭头函数。由于可能重复,未发布为答案:stackoverflow.com/questions/36648245/…
-
这里是编辑后的代码,移动了 setState 函数和 promise 的
thens 转换为箭头函数:codesandbox.io/s/g5Q6MZlRG -
@thenormalsquid 啊哈就是这样。我知道 ajax 和 setState 都是异步的,我知道我必须在 ajax 之后设置 setState,将它放在第一个“then”中,但我忘记了箭头函数。我想我必须复习一下关于“this”关键字及其上下文的知识。我遇到了您发布的答案,但我并没有真正从那里解决。非常感谢!
-
没问题!一个很好的理解范围的资源:@987654325@ 这是一篇关于箭头函数的很好的帖子:2ality.com/2012/04/arrow-functions.html
标签: javascript reactjs