未捕获(在承诺中)TypeError:当尝试在 ReactJs 中捕获 API 数据时,无法读取未定义的属性
2019-06-15
5974
我正在使用 ReactJS 开发货币转换器应用程序。该程序用于将一种货币转换为另一种货币。该应用程序有一个表单,其中包含一个带有提交按钮的字段。此外,它还默认初始货币为“10 美元”。
当用户在字段中输入货币缩写(例如:KRW)并单击提交按钮时。表单下方将显示从 USD 到 KRW 的转换结果。如果用户想要添加更多货币,则“KRW”转换结果下方将显示另一种选择货币。
当我尝试使函数在用户在字段中提交货币缩写时显示结果时。
这是错误:
Uncaught (in promise) TypeError: Cannot read property 'rates' of undefined
at Currency.render (App.js:402)
at finishClassComponent (react-dom.development.js:15319)
at updateClassComponent (react-dom.development.js:15274)
at beginWork (react-dom.development.js:16262)
at performUnitOfWork (react-dom.development.js:20279)
at workLoop (react-dom.development.js:20320)
at renderRoot (react-dom.development.js:20400)
at performWorkOnRoot (react-dom.development.js:21357)
at performWork (react-dom.development.js:21267)
at performSyncWork (react-dom.development.js:21241)
at requestWork (react-dom.development.js:21096)
at scheduleWork (react-dom.development.js:20909)
at Object.enqueueSetState (react-dom.development.js:11595)
at App.push../node_modules/react/cjs/react.development.js.Component.setState (react.development.js:336)
at Object.App.addCurrency [as onSubmit] (App.js:34)
at Form.handleSubmit (App.js:204)
这是我的代码:
class Currency extends React.Component {
render() {
const p = this.props;
return (
<div className="currency">
{/*<span className="currencyText"><Currency/></span>*/}
<div className="currencyInfo">
<div>{"1 "+p.base + " = " }</div>
<div>{p.data.rates}</div> {/*this is (App.js:402)*/}
</div>
</div>
);
}
}
相反,如果我像这样编写 Apps.js:402 代码:
<div>{p.data}</div>
并运行该应用程序,并检查 chrome 中的控制台,该行的结果为空。
我指的是图片上的数据:
这是控制台 prop p 的结果:
有没有什么解决方案,以便我可以从货币中检索数据汇率?
2个回答
理想情况下,您希望通过某种方式来管理组件中的
loading
和
no-data
状态,具体取决于您的 api 在没有数据时返回的内容 - 您可能必须以不同的方式进行管理,但这也是您应该涵盖的场景。您的数据似乎来自名为
rates
的 prop,而不是
data
,后者是一个具有多个键的对象。
我不确定您的代码结构,但这种迭代和检查加载/无数据状态也可能在父组件中完成。
class Currency extends React.Component {
render() {
const p = this.props;
const { rates = {} } = p;
const hasData = Object.keys(rates).length > 0;
return !p.loading ? (
<div className="currency">
<div className="currencyInfo">
{ hasData ?
<>
<div>{"1 "+p.base + " = " }</div>
{Object.entries(rates).map(([k, v]) => <div key={k}>{`${k}: ${v}`}</div>)}
</> : <p>No data available</p>
}
</div>
</div>
) : <Loader />
}
}
在父组件中,您可以执行以下操作:
class ParentComp extends React.Component {
public state = { loading: true, rates: {} };
componentDidMount() {
await this.fetchData(...); // could set loading to false on success
}
render() {
const { rates = {} } = this.state;
const hasData = Object.keys(rates).length > 0;
return (
!this.state.loading ?
hasData ?
Object.entries(rates).map(([k, v]) => <Currency key={k} name={k} value={v} ... />)
: <p>No data available</p>
: <Loader />
);
}
}
然后在您的子组件中:
class Currency extends React.Component {
render() {
return (
<div className='currency'>
<div className='currencyInfo'>
<div>{`${this.props.name}: ${this.props.value}`}</div>
</div>
</div>
);
}
}
致谢:
感谢 @Codebling 指出在键的
中不必要地添加v
(值)
deowk
2020-03-13
我假设您的货币组件是一个子组件,并且它有一个父组件。
在将“数据”传递给子组件之前,只需为其初始化一个值即可。
const Child = props => {
return(
<div>
Child
{props.data.country}
</div>
)
}
const Parent = props => {
// initiate state value to your variables that you are using.
let [data, set_data] = useState(
// this is where your error reside, you did not initiate a value.
{ country: 'abc'}
);
// api call
useEffect(()=>{
axios.get('http://ip-api.com/json/24.48.0.1',{})
.then(function (response) {
console.log(response.data);
set_data(response.data)
})
.catch(function (error) {
console.log(error.config);
});
}, [])
return(
<div>
Parent
<Child data={data}></Child>
</div>
)
}
export default Parent;
Mike Musni
2020-03-13