ReactJs: PropTypes ควรมีไว้เพื่ออะไร?


265

รับองค์ประกอบง่าย ๆ ที่ทำให้ลูก ๆ ของมัน:

class ContainerComponent extends Component {
  static propTypes = {
    children: PropTypes.object.isRequired,
  }

  render() {
    return (
      <div>
        {this.props.children}
      </div>
    );
  }
}

export default ContainerComponent;

คำถาม: เสาประเภทของเสาควรเป็นอย่างไร?

เมื่อฉันตั้งเป็นวัตถุมันล้มเหลวเมื่อฉันใช้องค์ประกอบที่มีลูกหลายคน:

<ContainerComponent>
  <div>1</div>
  <div>2</div>
</ContainerComponent>

คำเตือน: ไม่ประเภทเสา: เสาที่ไม่ถูกต้องchildrenจากประเภทarray จ่ายให้กับคาดว่าContainerComponentobject

ถ้าฉันตั้งค่าเป็นอาร์เรย์มันจะล้มเหลวถ้าฉันให้ลูกเพียงคนเดียวคือ:

<ContainerComponent>
  <div>1</div>
</ContainerComponent>

คำเตือน: โพรโทคอลที่ล้มเหลว: โพรไฟล์ลูกไม่ถูกต้องของออบเจ็กต์ประเภทที่จัดหาให้กับ ContainerComponent, อาร์เรย์ที่คาดไว้

กรุณาแนะนำฉันควรจะไม่รำคาญที่จะตรวจสอบ propTypes สำหรับองค์ประกอบของเด็ก ๆ ?


คุณอาจต้องการnode
lux


2
โปรดดูคำตอบของฉันด้านล่างที่อธิบายตัวเลือกเพิ่มเติม แต่ถ้าคุณกำลังมองหาลูกองค์ประกอบแล้วมันคือ PropTypes.element PropTypes.node อธิบายสิ่งที่สามารถแสดงผลได้ - สตริงตัวเลของค์ประกอบหรืออาร์เรย์ของสิ่งเหล่านี้ หากสิ่งนี้เหมาะกับคุณแล้วนี่คือวิธี
ggilberth

คำตอบ:


369

ลองใช้วิธีนี้oneOfTypeหรือPropTypes.node

import PropTypes from 'prop-types'

...

static propTypes = {
    children: PropTypes.oneOfType([
        PropTypes.arrayOf(PropTypes.node),
        PropTypes.node
    ]).isRequired
}

หรือ

static propTypes = {
    children: PropTypes.node.isRequired,
}

1
แต่น่าเสียดายที่มันล้มเหลวด้วยข้อผิดพลาดเหมือนกันในกรณีที่บุตรเดียว: "คำเตือน: ไม่ประเภทเสา: เสาที่ไม่ถูกต้องchildrenจากประเภทนี้object. ... คาดว่าอาร์เรย์"
d3ming

25
นั่นได้ผล! ทางออกที่ง่ายที่สุดคือchildren: PropTypes.nodeใช้ได้กับทั้งสองกรณี ขอบคุณสำหรับคำแนะนำ =)
d3ming

6
สิ่งเดียวที่จะทำให้คำตอบนี้ชัดเจนขึ้นคือถ้าคุณใส่บันทึกย่อที่คล้ายกับคำตอบของ @ggilberth เพื่ออธิบายว่าReact.PropTypes.nodeอธิบายถึงวัตถุใด ๆ ที่สามารถแสดงผลได้
theotherjim

ไม่จำเป็นต้องมีอาเรPropTypes.nodeย์ ที่จัดการการแก้ไขต่อไปนี้: ไม่มีอะไร, สตริง, องค์ประกอบเดียว, หลายองค์ประกอบ, ส่วน, ส่วนประกอบ
Dima Tisnek

38

สำหรับฉันมันขึ้นอยู่กับองค์ประกอบ หากคุณรู้ว่าคุณต้องการให้มีประชากรด้วยอะไรคุณควรพยายามระบุเฉพาะหรือหลายประเภทโดยใช้:

PropTypes.oneOfType 

อย่างไรก็ตามฉันส่วนใหญ่พบว่ามีองค์ประกอบทั่วไปมากขึ้นที่สามารถมีเด็กหลายประเภทฉันยินดีที่จะใช้:

PropTypes.any

หากคุณต้องการอ้างถึงส่วนประกอบ React คุณจะมองหา

PropTypes.element

แม้ว่า,

PropTypes.node

อธิบายสิ่งที่สามารถแสดงผลได้ - สตริงตัวเลของค์ประกอบหรืออาร์เรย์ของสิ่งเหล่านี้ หากสิ่งนี้เหมาะกับคุณแล้วนี่คือวิธี


7
Proptypes.anyเป็นประเภทที่พบบ่อยเกินไป Eslint ไม่มีความสุขกับสิ่งนั้น
Alex Shwarc

20

เอกสารประกอบ PropTypesมีดังต่อไปนี้

// Anything that can be rendered: numbers, strings, elements or an array
// (or fragment) containing these types.
optionalNode: PropTypes.node,

ดังนั้นคุณสามารถใช้PropTypes.nodeเพื่อตรวจสอบวัตถุหรืออาร์เรย์ของวัตถุ

static propTypes = {
   children: PropTypes.node.isRequired,
}

12

คำตอบที่นี่ดูเหมือนจะไม่ครอบคลุมการตรวจสอบเด็ก ๆ อย่างแน่นอน nodeและobjectอนุญาตเกินไปฉันต้องการตรวจสอบองค์ประกอบที่แน่นอน นี่คือสิ่งที่ฉันใช้:

  • ใช้oneOfType([])เพื่ออนุญาตให้ใช้สำหรับเด็กคนเดียวหรือหลายคน
  • ใช้shapeและarrayOf(shape({}))สำหรับเด็กเดี่ยวและอาร์เรย์ตามลำดับ
  • ใช้oneOfสำหรับองค์ประกอบลูกเอง

ในที่สุดสิ่งเช่นนี้:

import PropTypes from 'prop-types'
import MyComponent from './MyComponent'

children: PropTypes.oneOfType([
  PropTypes.shape({
    type: PropTypes.oneOf([MyComponent]),
  }),
  PropTypes.arrayOf(
    PropTypes.shape({
      type: PropTypes.oneOf([MyComponent]),
    })
  ),
]).isRequired

ปัญหานี้ช่วยให้ฉันเข้าใจเรื่องนี้ได้ชัดเจนยิ่งขึ้น: https://github.com/facebook/react/issues/2979


5

หากคุณต้องการจับคู่ประเภทส่วนประกอบให้ตรวจสอบสิ่งนี้

MenuPrimary.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(MenuPrimaryItem),
    PropTypes.objectOf(MenuPrimaryItem)
  ])
}

หากคุณต้องการจับคู่ส่วนประกอบบางประเภทให้ตรวจสอบสิ่งนี้

const HeaderTypes = [
  PropTypes.objectOf(MenuPrimary),
  PropTypes.objectOf(UserInfo)
]

Header.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.oneOfType([...HeaderTypes])),
    ...HeaderTypes
  ])
}

2

ลอง propTypes ที่กำหนดเอง:

 const  childrenPropTypeLogic = (props, propName, componentName) => {
          const prop = props[propName];
          return React.Children
                   .toArray(prop)
                   .find(child => child.type !== 'div') && new Error(`${componentName} only accepts "div" elements`);
 };


static propTypes = {

   children : childrenPropTypeLogic

}

ซอ


0

ตัวอย่าง:

import React from 'react';
import PropTypes from 'prop-types';

class MenuItem extends React.Component {
    render() {
        return (
            <li>
                <a href={this.props.href}>{this.props.children}</a>
            </li>
        );
    }
}

MenuItem.defaultProps = {
    href: "/",
    children: "Main page"
};

MenuItem.propTypes = {
    href: PropTypes.string.isRequired,
    children: PropTypes.string.isRequired
};

export default MenuItem;

รูปภาพ: แสดงข้อผิดพลาดในคอนโซลหากประเภทที่คาดไว้แตกต่าง

รูปภาพ: แสดงข้อผิดพลาดในคอนโซลหากประเภทที่คาดไว้แตกต่าง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.