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.statenextProps 是一个包含 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:如何检查收到的道具是不是未定义?的主要内容,如果未能解决你的问题,请参考以下文章

反应:作为道具的数组显示为未定义

React中传递道具和映射数据

react-redux connect 提供未定义的道具

react-router,道具“历史”未定义

我的道具在 React 的 ComponentDidMount 方法下的价值未定义

传递给子组件的道具未定义,但 console.log 显示道具的值