React:如何检查接收到的属性是否为未定义?

11

你好,感谢你的时间:

我正在按照以下教程操作:https://app.pluralsight.com/library/courses/react-flux-building-applications/table-of-contents

目前我已经发现,在尝试创建作者时,它会尝试加载当前作者URL的作者ID。由于它是正在被创建,所以它是未定义的,因此创建作者功能无法正常工作。

我已经阅读了一些关于在JS和React中检查未定义类型的主题:如何确定变量是“未定义”还是“null”?

在React中检查Undefined

https://github.com/facebook/react/issues/3725

我已经尝试了以下方法:

在manageAuthorForm中,我们将作者的状态传递给了作者表单:

  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

能帮我一下吗?

谢谢;=)


4
应该使用nextProps.author而不是nextProps.state.author - Titus
@enoy Titus的回答应该可以。 - RIYAJ KHAN
5个回答

7
简单的解决方案是:

<AuthorForm 
   author={this.state.author || {firstName:'', lastName:'', id:''}}
   ...
/>

请从子组件中删除componentWillReceiveProps方法。

更好的方法是:

1-author的初始值分配给状态,如下所示:

this.state = {
   author: {firstName:'', lastName:'', id:''}
}

2- 或者在子组件的渲染方法中,像这样编写:

render(){

   const {firstName='', lastName='', id=''} = this.props.author || {};

   return(....)
}

直接使用firstName,lastName,id,而不是this.props.

您代码中的问题:

1- 在componentWillReceiveProps生命周期方法中,应该使用nextProps.author而不是nextProps.state.author

2- Props 是只读的,无论您将组件声明为函数还是类,它都不应该修改自己的props。您正在尝试在componentWillReceiveProps中更改值。


感谢@Mayank Shukla提供的三种解决方案。我已经尝试了更简单的方法并且它有效,以及你推荐的第二种方法。然而,我不理解你推荐的第一种方法。我应该在哪里初始化作者的状态?感谢你的帮助。 - Yone
应该在父组件中渲染AuthorForm组件并将author数据传递给它。 - Mayank Shukla

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无法被更新,将其放置在状态中以便以后使用更加合理。如果您需要接收prop更新,请在componentWillUpdate()中使用setState()

另一种更冗长的解决方案是将author设置为必需的prop,并且直到存在必要的props时才尝试创建该组件。这也是更好的实践。

AuthorForm.propTypes = {
  author: PropTypes.string.isRequired,
};

0

你应该将默认值设置为 {this.state.author},而不是将默认值设置为 props 到组件中


0

nextProps.state?

有状态的是组件,请决定您将在组件属性或状态中处理author数据。

此外,您还应该查看:https://www.npmjs.com/package/prop-types

这是一个用于React处理组件属性类型和默认值的库。使用此库,您将能够执行以下操作:

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,
};

0

const UndefinedCheck =  data => {
    if(data === undefined){
        return 1
    }else {
        return data
    }
}

export default UndefinedCheck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接