很抱歉,标题令人困惑。但是如果你点击源代码就可以看到我有一个组件名称Search。内部搜索是一个函数handleSearchSubmit
,当用户单击渲染函数内的搜索按钮时,它会激活。现在我的问题是我现在要更新trackViewer
内的列表。每个列表项都应填充{title}
,<ul>
应调用{trackItems}
。但无论我做什么,我似乎都可以让列表更新。如果我不包含this
,那么变量t rackItems
在渲染函数中是未定义的。那我究竟做错了什么?这应该是同一文件或新文件中的单独组件吗?
答案 0 :(得分:0)
您的trackItems变量是一个未附加到您的类的局部变量,因此您无法通过渲染函数中的this.trackItems访问它
const trackItems = trackTitle.map((titles) =>
<li>{titles}</li>
);
所以快速修复,完全取消trackItems变量,而不是在渲染函数中运行该代码片段:
render(){
return(
<form>
<input type="text" value={this.state.value} placeholder="Enter a Artist, Song, or Album.." onChange={this.handleChange}/>
<button type="button" onClick={this.handleSearchSubmit}>Search</button>
<div id="trackViewer">
<p>Results for: {this.state.value}</p>
<ul>{trackTitle.map((titles) =><li>{titles}</li>)}</ul>
</div>
</form>
)
}
答案 1 :(得分:0)
据我所知,这里所需的行为是从API获取数据并在接收时显示它。 实现React的基本思想非常重要。当且仅当它的状态或上游道具发生变化时,该组件才会重新渲染。这就是你需要的。使用状态更改来触发重新渲染。
import React, { Component } from 'react';
import { client_id } from './config';
import 'isomorphic-fetch';
import 'whatwg-fetch';
import SC from 'soundcloud';
import ReactDOM from 'react-dom';
// This is not a good place for such data, all data should be encapsulated accordingly
let search = "https://api.soundcloud.com/tracks?&client_id="+ client_id +"&limit=50&offset=0&q="+query;
let tags = "https://api.soundcloud.com/tracks?linked_partitioning=1&client_id="+ client_id +"&limit=50&offset=0&tags=deep%20house";
class Search extends Component{
constructor(props){
super(props);
this.state = {
value: '',
// Moved trackTitle from above into the state
trackTitle: []
};
};
handleChange(event){
event.preventDefault();
this.setState({ value: event.target.value });
}
handleSearchSubmit(){
event.preventDefault();
// Create local scope buffer for trackTitles to store in state in the end
let trackTitleBuffer = []
// You can use shortened expression instead of client_id: client_id, hail ES2015!
SC.initialize({ client_id });
// You don't really need query variable, use state directly
// Using arrow functions for readability
fetch(search + this.state.value, { method:"GET" })
.then(response => response.json())
.catch(error => console.log(error))
.then(json => {
json.map(entity => trackTitleBuffer.push(entity.title))
// And pour it all to the state.trackTitle
// This is important, you only to want to re-render when you have all the track titles ready
// If you pushed the track titles to the state one-by-one, every push would trigger a re-render
// It might look cool as well as it might not
this.setState({ trackTitle: trackTitleBuffer })
})
.catch(error => console.log(error))
};
render(){
// Desctructuring the state
const { trackTitle, value } = this.state
return(
<form>
<input type="text" value={this.state.value} placeholder="Enter a Artist, Song, or Album.." onChange={event => this.handleChange(event)}/>
<button type="button" onClick={() => this.handleSearchSubmit()}>Search</button>
<div id="trackViewer">
<p>Results for: {value}</p>
<ul>{ trackTitle.map(title => <li key={title)}>{title}</li>) }</ul>
</div>
</form>
)
};
};
export default Search;