React:如何检查收到的道具是否未定义?

时间:2018-02-14 14:24:24

标签: javascript reactjs

您好,感谢您的时间:

我遵循以下教程: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

你能帮助我吗?

谢谢; =)

5 个答案:

答案 0 :(得分:4)

简单的解决方案是:

<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-在nextProps.author生命周期方法中应该是nextProps.state.author而不是componentWillReceiveProps

2- Props are read-only ,无论是将组件声明为函数还是类,它都不能修改自己的道具。您正尝试更改componentWillReceiveProps中的值。

答案 1 :(得分:2)

您的错误讯息是; Cannot read property 'author' of undefined

实际上author不是nextProps.state,而是nextPropscomponentWillReceiveProps()是一个对象,其中包含道具的内容。

这里的另一个问题是,在安装时不会调用props.author,因此如果constructor(props) { super(props); this.state = { author: this.props.author, }; } 最初未定义,那么错误处理将无法正常工作。 Mayank Shukla有一个很好的答案,但是要求你有这样的构造函数;

setState()

由于道具无法更新,因此将其置于状态更有意义,以便将来可以使用。如果您需要接收道具更新,请使用componentWillUpdate()

中的author

另一个更长时间的解决方案是让AuthorForm.propTypes = { author: PropTypes.string.isRequired, }; 成为必需的道具,而不是在必要的道具存在之前尝试创建该组件。这也是更好的做法。

Node* Insert(Node *head,int data)
{
  // Complete this method
   Node *temp, *temp1;
   temp1 = head;
   temp = (Node *)malloc(sizeof(Node));
   temp->data = data;
   temp->next = NULL;
   if(head==NULL) head=temp; //ADDED THIS LINE
   else{
     while(temp1->next!=NULL){
        temp1 = temp1->next;
     }
   temp1->next = temp;
   }
  return head;
}

答案 2 :(得分:0)

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

答案 3 :(得分:0)

nextProps.state?

具有状态的组件,请确定您将在何处处理author数据。在组件道具或状态。

除此之外,你应该看看: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,
};

答案 4 :(得分:0)

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

export default UndefinedCheck