React:如何检查收到的道具是不是未定义?
Posted
技术标签:
【中文标题】React:如何检查收到的道具是不是未定义?【英文标题】:React: How to check if received props are undefined?React:如何检查收到的道具是否未定义? 【发布时间】:2018-07-25 03:53:37 【问题描述】:您好,感谢您抽出宝贵时间:
我正在学习以下教程:https://app.pluralsight.com/library/courses/react-flux-building-applications/table-of-contents
目前我检测到,当您尝试创建作者时,它会尝试加载当前作者的 URL 的作者 ID。因为它正在被创建,它是未定义的,所以创建作者功能不起作用。
我已经阅读了一些关于在 JS 和 React 中检查未定义类型的主题: How to determine if variable is 'undefined' or 'null'?
Checking for Undefined In React
https://github.com/facebook/react/issues/3725
我已经尝试了以下方法:
在manageAuthorForm中我们将作者的状态传递给authorForm:
render()
return (
<AuthorForm author=this.state.author
onChange=this.setAuthorState
onSave=this.saveAuthor/>
);
;
然后我尝试进入 AuthorForm:
import React from 'react';
import Input from "../common/textInput";
import Link from "react-router-dom/es/Link";
class AuthorForm extends React.Component
componentWillReceiveProps(nextProps)
if (nextProps.state.author === undefined)
this.props.author =
author:
id: '',
firstName: '',
lastName: '',
;
render()
return (
<form>
<h1>Manage author</h1>
<Input
name="firstName"
label="First Name"
value=this.props.author.firstName
onChange=this.props.onChange
/>
<Input
name="lastName"
label="Last Name"
value=this.props.author.lastName
onChange=this.props.onChange
/>
<button type="submit" value="Save" className="btn btn-default" onClick=this.props.onSave><Link
to="/authors">Save
author</Link>
</button>
</form>
);
export AuthorForm
它报告 nextProps 未定义:
Uncaught TypeError: Cannot read property 'author' of undefined
at AuthorForm.componentWillReceiveProps (authorForm.js:7)
at callComponentWillReceiveProps (react-dom.development.js:6389)
at updateClassInstance (react-dom.development.js:6575)
at updateClassComponent (react-dom.development.js:7848)
at beginWork (react-dom.development.js:8225)
at performUnitOfWork (react-dom.development.js:10224)
at workLoop (react-dom.development.js:10288)
at htmlUnknownElement.callCallback (react-dom.development.js:542)
at Object.invokeGuardedCallbackDev (react-dom.development.js:581)
at invokeGuardedCallback (react-dom.development.js:438)
at renderRoot (react-dom.development.js:10366)
at performWorkOnRoot (react-dom.development.js:11014)
at performWork (react-dom.development.js:10967)
at requestWork (react-dom.development.js:10878)
at scheduleWorkImpl (react-dom.development.js:10732)
at scheduleWork (react-dom.development.js:10689)
at scheduleTopLevelUpdate (react-dom.development.js:11193)
at Object.updateContainer (react-dom.development.js:11231)
at react-dom.development.js:15226
at Object.unbatchedUpdates (react-dom.development.js:11102)
at renderSubtreeIntoContainer (react-dom.development.js:15225)
at Object.render (react-dom.development.js:15290)
at Object../src/index.js (index.js:17)
at __webpack_require__ (bootstrap 78b34f0f34b98a41c613:678)
at fn (bootstrap 78b34f0f34b98a41c613:88)
at Object.0 (authorStore.js:39)
at __webpack_require__ (bootstrap 78b34f0f34b98a41c613:678)
at bootstrap 78b34f0f34b98a41c613:724
at bootstrap 78b34f0f34b98a41c613:724
componentWillReceiveProps @ authorForm.js:7
callComponentWillReceiveProps @ react-dom.development.js:6389
updateClassInstance @ react-dom.development.js:6575
updateClassComponent @ react-dom.development.js:7848
beginWork @ react-dom.development.js:8225
performUnitOfWork @ react-dom.development.js:10224
workLoop @ react-dom.development.js:10288
callCallback @ react-dom.development.js:542
invokeGuardedCallbackDev @ react-dom.development.js:581
invokeGuardedCallback @ react-dom.development.js:438
renderRoot @ react-dom.development.js:10366
performWorkOnRoot @ react-dom.development.js:11014
performWork @ react-dom.development.js:10967
requestWork @ react-dom.development.js:10878
scheduleWorkImpl @ react-dom.development.js:10732
scheduleWork @ react-dom.development.js:10689
scheduleTopLevelUpdate @ react-dom.development.js:11193
updateContainer @ react-dom.development.js:11231
(anonymous) @ react-dom.development.js:15226
unbatchedUpdates @ react-dom.development.js:11102
renderSubtreeIntoContainer @ react-dom.development.js:15225
render @ react-dom.development.js:15290
./src/index.js @ index.js:17
__webpack_require__ @ bootstrap 78b34f0f34b98a41c613:678
fn @ bootstrap 78b34f0f34b98a41c613:88
0 @ authorStore.js:39
__webpack_require__ @ bootstrap 78b34f0f34b98a41c613:678
(anonymous) @ bootstrap 78b34f0f34b98a41c613:724
(anonymous) @ bootstrap 78b34f0f34b98a41c613:724
并在网络浏览器中报告:
×
TypeError: Cannot read property 'author' of undefined
AuthorForm.componentWillReceiveProps
C:/Users/YonePC/WebstormProjects/flux/src/components/authors/authorForm.js:7
4 |
5 | class AuthorForm extends React.Component
6 | componentWillReceiveProps(nextProps)
> 7 | if (nextProps.state.author === undefined)
8 | this.props.author =
9 | author:
10 | id: '',
View compiled
▶ 15 stack frames were collapsed.
This screen is visible only in development. It will not appear if the app crashes in production.
Open your browser’s developer console to further inspect this error.
完整代码,在github:https://github.com/YoneMoreno/ReactFluxAuthorsPageTutorial
你能帮帮我吗?
谢谢;=)
【问题讨论】:
应该是nextProps.author
而不是nextProps.state.author
。
@enoy Titus 的回答应该可以。
【参考方案1】:
简单的解决方案是:
<AuthorForm
author=this.state.author || firstName:'', lastName:'', id:''
...
/>
并从子组件中删除componentWillReceiveProps
方法。
更好的方法将是:
1-将author
的初始值赋值为:
this.state =
author: firstName:'', lastName:'', id:''
2-或者在子组件的render方法里面,这样写:
render()
const firstName='', lastName='', id='' = this.props.author || ;
return(....)
并且直接使用firstName, lastName, id
而不是this.props.
代码中的问题:
1- 在componentWillReceiveProps
生命周期方法中应该是nextProps.author
而不是nextProps.state.author
。
2- Props are read-only,无论你将组件声明为函数还是类,它都不能修改自己的props。您正在尝试更改 componentWillReceiveProps
中的值。
【讨论】:
感谢@Mayank Shukla 提供的三个解决方案。我已经尝试过更简单的方法,它以及您推荐的第二种方法也有效。但是,第一个推荐的方法是我不明白的方法。我应该在哪里初始化作者的状态?感谢您的帮助。 它应该在您渲染AuthorForm
组件并将author
数据传递给它的父组件中。【参考方案2】:
您的错误信息是;
Cannot read property 'author' of undefined
实际上未定义的不是author
,而是nextProps.state
。 nextProps
是一个包含 仅 props 内容的对象。
这里的另一个问题是在挂载时没有调用componentWillReceiveProps()
,因此如果最初未定义props.author
,那么错误处理将不起作用。 Mayank Shukla 有一个很好的答案,但这需要你有一个这样的构造函数;
constructor(props)
super(props);
this.state =
author: this.props.author,
;
由于 props 无法更新,因此将其置于 state 中以便将来可以使用更有意义。如果您需要接收道具更新,请在componentWillUpdate()
中使用setState()
另一个更冗长的解决方案是使author
成为必需的道具,并且在必要的道具存在之前不要尝试创建该组件。这也是更好的做法。
AuthorForm.propTypes =
author: PropTypes.string.isRequired,
;
【讨论】:
【参考方案3】:您应该将默认值设置为您设置为组件的 this.state.author 而不是将默认值设置为 props
【讨论】:
【参考方案4】:nextProps.state ?
有状态的是组件,请决定你要去哪里处理author
数据。在组件 props 或 state 中。
另外你应该看看:https://www.npmjs.com/package/prop-types
它是一个库,用于处理组件道具的类型和默认值。使用这个库,您将能够执行以下操作:
FunctionPointAutomatedTable.defaultProps =
dataSource: [],
;
FunctionPointAutomatedTable.propTypes =
applicationId: PropTypes.string,
functionType: PropTypes.string,
dataSource: PropTypes.array,
allowedTypes: PropTypes.array,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
onIgnore: PropTypes.func,
onMerge: PropTypes.func,
onUnmerge: PropTypes.func,
;
【讨论】:
【参考方案5】:const UndefinedCheck = data =>
if(data === undefined)
return 1
else
return data
export default UndefinedCheck
【讨论】:
以上是关于React:如何检查收到的道具是不是未定义?的主要内容,如果未能解决你的问题,请参考以下文章