[英]Display data from an API when clicking a button. Using ReactJS
I am trying to display the data of each character when I click the Info Button.当我单击信息按钮时,我试图显示每个字符的数据。 I know it is because in the
onButtonClickHandler
function it can not see the state.我知道这是因为在
onButtonClickHandler
函数中它看不到状态。 I have also tried this.state.person
but it gives me an error saying "can not read state".我也试过
this.state.person
但它给了我一个错误,说“无法读取状态”。 And if I try just state.person
it will give me "undefined".如果我只尝试
state.person
它会给我“未定义”。
What is the best way to do that?最好的方法是什么? Thank you
谢谢
API Link: https://swapi.dev/people/ API 链接: https : //swapi.dev/people/
import React from "react";
export default class FetchActors extends React.Component {
state = {
loading: true,
person: null
};
async componentDidMount() {
const url = "https://swapi.dev/api/people/";
const response = await fetch(url);
const data = await response.json();
this.setState({ person: data.results, loading: false });
}
render() {
if (this.state.loading) {
return <div>loading...</div>;
}
if (!this.state.person.length) {
return <div>didn't get a person</div>;
}
function onButtonClickHandler(state) {
console.log(state.person);
};
return (
<div>
<h1>Actors</h1>
{this.state.person.map(person =>(
<div>
<div>
{person.name}
<button onClick={onButtonClickHandler}>Info</button>
</div>
</div>
))}
<button onClick={onButtonClickHandler}>Enter</button>
</div>
);
}
}
Please correct me if I'm wrong如果我错了,请纠正我
The most likely reason why you are seeing this is because of the way javascript internally works.您看到这种情况的最可能原因是 javascript 内部的工作方式。 The syntax:
语法:
function xyz() {
}
has an implicit this
有一个隐含的
this
Maybe try changing your code from:也许尝试从以下位置更改您的代码:
function onButtonClickHandler(state) {
console.log(state.person);
};
to:到:
const onButtonClickHandler = () => {
console.log(this.state.person);
};
there are a few ways you can resolve your issue;有几种方法可以解决您的问题; I'll give you the more common approach.
我会给你更常见的方法。
class Actors extends React.Component {
state = {
loading: false,
actors: undefined,
};
constructor(props) {
super(props);
this.fetchActors = this.fetchActors.bind(this);
}
async fetchActors() {
this.setState({ loading: true });
const url = "https://swapi.dev/api/people/";
const response = await fetch(url);
const data = await response.json();
this.setState({ actors: data.results, loading: false });
}
render() {
console.log('Actors: ', this.state.actors);
return <button onClick={this.fetchActors}>fetch actors</button>;
}
}
You have defined your function onButtonClickHandler
as a function that takes one argument, and logs the person
property of that argument.您已将函数
onButtonClickHandler
定义为接受一个参数并记录该参数的person
属性的函数。 The argument state
in your function has nothing to do with the state
of your component.函数中的参数
state
与组件的state
无关。 As javascript sees it, they are two totally unrelated variables which just happen to have the same name.正如 javascript 所见,它们是两个完全不相关的变量,只是碰巧具有相同的名称。
function onButtonClickHandler(state) {
console.log(state.person);
};
When button
calls onClick
, it passes the event as the argument.当
button
调用onClick
,它将事件作为参数传递。 So your onButtonClickHandler
is logging the person
property of the event, which obviously doesn't exist.所以你的
onButtonClickHandler
正在记录事件的person
属性,这显然不存在。
Since you are not using any information from the event, your function should take no arguments.由于您没有使用事件中的任何信息,因此您的函数不应采用任何参数。 As others have said, you should also move this function outside of the
render()
method so that it is not recreated on each render.正如其他人所说,您还应该将此函数移到
render()
方法之外,以便不会在每次渲染时重新创建它。 The suggestion to use bind
is not necessary if you use an arrow function, since these bind automatically.如果您使用箭头函数,则不需要使用
bind
的建议,因为它们会自动绑定。
export default class FetchActors extends React.Component {
/*...*/
onButtonClickHandler = () => {
console.log(this.state.person);
};
}
Inside render()
内部
render()
<button onClick={this.onButtonClickHandler}>Enter</button>
You could also define the function inline, as an arrow function which takes no arguments:您还可以将函数内联定义为不带参数的箭头函数:
<button onClick={() => console.log(this.state.person)}>Enter</button>
If you are new to react, I recommend learning with function components rather than class components.如果您不熟悉 React,我建议您使用函数组件而不是类组件来学习。
Edit:编辑:
Updating this answer regarding our comments.更新有关我们评论的答案。 I was so caught up in explaining the errors from doing the wrong thing that I neglected to explain how to do the right thing!
我太忙于解释做错事的错误,以至于忽略了解释如何做正确的事!
I am trying to display the data of each character when I click the Info Button.
当我单击信息按钮时,我试图显示每个字符的数据。
Once we call the API, we already have the info loaded for each character.一旦我们调用 API,我们就已经为每个角色加载了信息。 We just need to know which one we want to display.
我们只需要知道我们想要显示哪一个。 You can add a property
expanded
to your state
and use it to store the index (or id
or name
, whatever you want really) of the currently expanded item.您可以添加一个
expanded
到您的state
的属性,并使用它来存储当前扩展项目的索引(或id
或name
,无论您想要什么)。
When we loop through to show the name and info button, we check if that character is the expanded one.当我们循环显示名称和信息按钮时,我们检查该字符是否是展开的字符。 If so, we show the character info.
如果是这样,我们会显示字符信息。
Now the onClick
handler of our button is responsible for setting state.expanded
to the character that we clicked it from.现在我们按钮的
onClick
处理程序负责将state.expanded
设置为我们单击它的字符。
{this.state.person.map((person, i) =>(
<div>
<div>
{person.name}
<button onClick={() => this.setState({expanded: i})}>Info</button>
{this.state.expanded === i && (
<CharacterInfo
key={person.name}
person={person}
/>
)}
</div>
Sometimes i takes react a min to load the updated state.有时我需要一分钟的时间来加载更新的状态。
import React from "react";
export default class FetchActors extends React.Component {
state = {
loading: true,
person: null
};
async componentDidMount() {
const url = "https://swapi.dev/api/people/";
const response = await fetch(url);
const data = await response.json();
if(!data.results) { // throw error }
this.setState({ person: data.results, loading: false }, () => {
console.log(this.state.person) // log out your data to verify
});
}
render() {
if (this.state.loading || !this.state.person) { // wait for person data
return <div>loading...</div>;
}else{
function onButtonClickHandler(state) { // just make a componentDidUpdate function
console.log(state.person);
};
return (
<div>
<h1>Actors</h1>
{this.state.person.map(person =>(
<div>
<div>
{person.name}
<button onClick={onButtonClickHandler}>Info</button>
</div>
</div>
))}
<button onClick={onButtonClickHandler}>Enter</button>
</div>
);
}
}}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.