我正在构建一个微型应用程序,我想使其更清洁。
所以基本上我想拥有3个组成部分:App
,List
和Person
。
这是代码: App.js
import React, { Component } from "react";
import List from './List';
class App extends Component {
constructor(props) {
super(props);
this.state = {
results: [],
search: '',
currentPage: 1,
todosPerPage: 3
};
this.handleClick = this.handleClick.bind(this);
}
componentWillMount() {
this.fetchData();
}
fetchData = async () => {
const response = await fetch(API);
const json = await response.json();
this.setState({ results: json.results });
};
handleClick(event) {
this.setState({
currentPage: Number(event.target.id)
});
}
updateSearch(event) {
this.setState({ search: event.target.value.substr(0, 20) });
}
render() {
return (
<List />
);
}
}
export default App;
List.js
import React, { Component } from 'react';
import Person from './Person';
class List extends Component {
render() {
const { results, currentPage, todosPerPage } = this.state;
const indexOfLastTodo = currentPage * todosPerPage;
const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
const currentTodos = results.slice(indexOfFirstTodo, indexOfLastTodo).filter(item => {
return item.name.toLowerCase().indexOf(this.state.search) !== -1;
});
const renderTodos = currentTodos.map((item, index) => {
return (
<Person item={this.state.item} index={this.state.index}/>
);
});
const pageNumbers = [];
for (let i = 1; i <= Math.ceil(results.length / todosPerPage); i++) {
pageNumbers.push(i);
}
const renderPageNumbers = pageNumbers.map(number => {
return (
<li className="page-link" key={number} id={number} onClick={this.handleClick} style={{cursor: "pointer"}}>{number}</li>
);
});
return (
<div className="flex-grow-1">
<h1>Personnages de Star Wars</h1>
<form className="mb-4">
<div className="form-group">
<label>Rechercher</label>
<input
className="form-control"
type="text"
placeholder="luke skywalker..."
value={this.state.search}
onChange={this.updateSearch.bind(this)}
/>
</div>
</form>
<div className="row mb-5">{renderTodos}</div>
<nav aria-label="Navigation">
<ul id="page-number" className="pagination justify-content-center">{renderPageNumbers}</ul>
</nav>
</div>
);
}
}
export default List;
Person.js
import React, { Component } from 'react';
function Person(item, index) {
return (
<div className="col-lg-4 mb-4" key={index}>
<div className="card">
<div className="card-header">
<h4 className="mb-0">{item.name}</h4>
</div>
<div className="card-body">
<h5 className="card-title">Caractéristiques</h5>
<ul>
<li>Année de naissance : {item.birth_year}</li>
<li>Taille : {item.height} cm</li>
<li>Masse : {item.mass}</li>
<li>Couleur des yeux : {item.eye_color}</li>
<li>Couleur de cheveux : {item.hair_color}</li>
<li>Couleur de peau : {item.skin_color}</li>
</ul>
<a href={item.url} className="btn btn-primary">Sa fiche</a>
</div>
</div>
</div>
)
}
export default Person;
我的问题是渲染时得到TypeError: Cannot read property 'results' of null
。
如果我在App.js
中定义了每个文件,是否可以将变量放入每个文件中?
答案 0 :(得分:1)
您可以在<List />
组件的props中使用传递变量,方法是在调用<List />
时在App.js的render函数中传递状态
render() {
//Passing Data inside props
<List data={this.state} />
}
在List.js中,您可以访问数据变量
const { results, currentPage, todosPerPage } = this.props.data;
答案 1 :(得分:1)
您没有以正确的方式传递数据。试试这个:
在App.js中,将所需数据传递给List组件:
render() {
return (
<List data={this.state}/>
);
}
然后在List.js中的render()方法中获取传递的数据属性,然后从那里提取数据:
render() {
const { data } = this.props;
const { results, search, currentPage, todosPerPage } = data;
// ...
// in currentTodos function dont use this.state.search but just "search", that we got above from the data variable
// ...
// also your renderTodos should look like this - use the item and index variables
const renderTodos = currentTodos.map((item, index) => {
return (
<Person item={item} index={index}/>
);
});
// ...
}
因此您的List.js应该如下所示:
import React, { Component } from 'react';
import Person from './Person';
class List extends Component {
render() {
// get the data
const { data } = this.props;
// get the properties
const { results, search, currentPage, todosPerPage } = data;
const indexOfLastTodo = currentPage * todosPerPage;
const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
const currentTodos = results.slice(indexOfFirstTodo, indexOfLastTodo).filter(item => {
// use "search" variable
return item.name.toLowerCase().indexOf(search) !== -1;
});
const renderTodos = currentTodos.map((item, index) => {
return (
// use item and index
<Person item={item} index={index}/>
);
});
const pageNumbers = [];
for (let i = 1; i <= Math.ceil(results.length / todosPerPage); i++) {
pageNumbers.push(i);
}
const renderPageNumbers = pageNumbers.map(number => {
return (
<li className="page-link" key={number} id={number} onClick={this.handleClick} style={{cursor: "pointer"}}>{number}</li>
);
});
return (
<div className="flex-grow-1">
<h1>Personnages de Star Wars</h1>
<form className="mb-4">
<div className="form-group">
<label>Rechercher</label>
<input
className="form-control"
type="text"
placeholder="luke skywalker..."
value={search} // use search variable here too
onChange={this.updateSearch.bind(this)}
/>
</div>
</form>
<div className="row mb-5">{renderTodos}</div>
<nav aria-label="Navigation">
<ul id="page-number" className="pagination justify-content-center">{renderPageNumbers}</ul>
</nav>
</div>
);
}
}
export default List;
Person.js中的函数应具有以下声明,因为参数是从传递的道具中提取的:
function Person({item, index}) {
// ...
}