반응 성분에서 특정 유형의 아이만 허용
나는 가지고 있다Card
컴포넌트와 aCardGroup
컴포넌트입니다.또한 에러를 발생시키고 싶습니다.CardGroup
그렇지 않은 아이가 있다Card
구성 요소들.이게 가능한가요?아니면 제가 잘못된 문제를 해결하려고 하는 건가요?
Respect 0.14+ 및 ES6 클래스를 사용하는 경우 솔루션은 다음과 같습니다.
class CardGroup extends Component {
render() {
return (
<div>{this.props.children}</div>
)
}
}
CardGroup.propTypes = {
children: function (props, propName, componentName) {
const prop = props[propName]
let error = null
React.Children.forEach(prop, function (child) {
if (child.type !== Card) {
error = new Error('`' + componentName + '` children should be of type `Card`.');
}
})
return error
}
}
각 아이에 대해 displayName을 사용할 수 있으며 다음 유형을 통해 액세스할 수 있습니다.
for (child in this.props.children){
if (this.props.children[child].type.displayName != 'Card'){
console.log("Warning CardGroup has children that aren't Card components");
}
}
어린이는 소품일 뿐이므로 커스텀 propType 함수를 사용하여 어린이를 검증할 수 있습니다.자세한 내용을 원하시면 기사도 작성했습니다.
var CardGroup = React.createClass({
propTypes: {
children: function (props, propName, componentName) {
var error;
var prop = props[propName];
React.Children.forEach(prop, function (child) {
if (child.type.displayName !== 'Card') {
error = new Error(
'`' + componentName + '` only accepts children of type `Card`.'
);
}
});
return error;
}
},
render: function () {
return (
<div>{this.props.children}</div>
);
}
});
TypeScript 버전을 사용하는 사용자용.다음과 같이 구성 요소를 필터링/수정할 수 있습니다.
this.modifiedChildren = React.Children.map(children, child => {
if (React.isValidElement(child) && (child as React.ReactElement<any>).type === Card) {
let modifiedChild = child as React.ReactElement<any>;
// Modifying here
return modifiedChild;
}
// Returning other components / string.
// Delete next line in case you dont need them.
return child;
});
를 사용합니다.React.Children.forEach
아이들에 대해 반복하고 사용하는 방법name
유형을 확인할 속성:
React.Children.forEach(this.props.children, (child) => {
if (child.type.name !== Card.name) {
console.error("Only card components allowed as children.");
}
}
사용하는 것을 추천합니다.Card.name
대신'Card'
더 나은 유지 보수와 안정성을 위해 끈을 사용합니다.
참조: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
유형 불일치 오류를 피하기 위해 유형 스크립트를 사용하는 경우 "Child.type"과 함께 "React.isValidElement(child)"를 사용해야 합니다.
React.Children.forEach(props.children, (child, index) => {
if (React.isValidElement(child) && child.type !== Card) {
error = new Error(
'`' + componentName + '` only accepts children of type `Card`.'
);
}
});
소품을 추가할 수 있습니다.Card
컴포넌트 및 컴포넌트를 사용하여CardGroup
요소.이것이 리액트에서 이를 달성하는 가장 안전한 방법입니다.
이 소품은 defaultProp로 추가할 수 있으므로 항상 사용할 수 있습니다.
class Card extends Component {
static defaultProps = {
isCard: true,
}
render() {
return (
<div>A Card</div>
)
}
}
class CardGroup extends Component {
render() {
for (child in this.props.children) {
if (!this.props.children[child].props.isCard){
console.error("Warning CardGroup has a child which isn't a Card component");
}
}
return (
<div>{this.props.children}</div>
)
}
}
를 사용하여 Card 컴포넌트가 실제로 Card 컴포넌트인지 확인type
또는displayName
님은, https://github.com/facebook/react/issues/6167#issuecomment-191243709 에 나타나 있듯이, 실가동시에 동작하지 않을 가능성이 있기 때문에 안전하지 않습니다.
이를 위해 커스텀 PropType을 만들었습니다.equalTo
이렇게 쓸 수 있어요
class MyChildComponent extends React.Component { ... }
class MyParentComponent extends React.Component {
static propTypes = {
children: PropTypes.arrayOf(PropTypes.equalTo(MyChildComponent))
}
}
지금이다,MyParentComponent
어린애들만 받아들인다MyChildComponent
이런 html 요소를 확인할 수 있습니다.
PropTypes.equalTo('h1')
PropTypes.equalTo('div')
PropTypes.equalTo('img')
...
구현은 다음과 같습니다.
React.PropTypes.equalTo = function (component) {
return function validate(propValue, key, componentName, location, propFullName) {
const prop = propValue[key]
if (prop.type !== component) {
return new Error(
'Invalid prop `' + propFullName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
};
}
여러 가지 유형 중 하나를 받아들이도록 쉽게 확장할 수 있습니다.아마도...
React.PropTypes.equalToOneOf = function (arrayOfAcceptedComponents) {
...
}
static propTypes = {
children : (props, propName, componentName) => {
const prop = props[propName];
return React.Children
.toArray(prop)
.find(child => child.type !== Card) && new Error(`${componentName} only accepts "<Card />" elements`);
},
}
React 요소의 유형을 검증할 수 있는 패키지를 공개했습니다.https://www.npmjs.com/package/react-element-proptypes :
const ElementPropTypes = require('react-element-proptypes');
const Modal = ({ header, items }) => (
<div>
<div>{header}</div>
<div>{items}</div>
</div>
);
Modal.propTypes = {
header: ElementPropTypes.elementOfType(Header).isRequired,
items: React.PropTypes.arrayOf(ElementPropTypes.elementOfType(Item))
};
// render Modal
React.render(
<Modal
header={<Header title="This is modal" />}
items={[
<Item/>,
<Item/>,
<Item/>
]}
/>,
rootElement
);
올바른 아동 컴포넌트를 검증하기 위해 react children forach와 Custom validation proptypes의 사용을 조합합니다.이것에 의해, 마지막에 다음과 같은 것이 가능하게 됩니다.
HouseComponent.propTypes = {
children: PropTypes.oneOfType([(props, propName, componentName) => {
let error = null;
const validInputs = [
'Mother',
'Girlfried',
'Friends',
'Dogs'
];
// Validate the valid inputs components allowed.
React.Children.forEach(props[propName], (child) => {
if (!validInputs.includes(child.type.name)) {
error = new Error(componentName.concat(
' children should be one of the type:'
.concat(validInputs.toString())
));
}
});
return error;
}]).isRequired
};
보시는 바와 같이 가 올바른 유형의 이름으로 배열되어 있습니다.
한편, Airbnb/prop-type 라이브러리에서 componentWithName이라는 동일한 결과를 얻을 수 있는 기능도 있습니다.자세한 내용은 이쪽에서 확인하실 수 있습니다.
HouseComponent.propTypes = {
children: PropTypes.oneOfType([
componentWithName('SegmentedControl'),
componentWithName('FormText'),
componentWithName('FormTextarea'),
componentWithName('FormSelect')
]).isRequired
};
이것이 도움이 되기를 바랍니다:)
제안된 접근방식을 여러 개 검토했지만, 모두 신뢰할 수 없거나 지나치게 복잡하여 보일러 플레이트로 사용할 수 없는 것으로 판명되었습니다.이하의 실장에 대해 결정.
class Card extends Component {
// ...
}
class CardGroup extends Component {
static propTypes = {
children: PropTypes.arrayOf(
(propValue, key, componentName) => (propValue[key].type !== Card)
? new Error(`${componentName} only accepts children of type ${Card.name}.`)
: null
)
}
// ...
}
주요 아이디어는 다음과 같습니다.
- 의 「」를 합니다.
PropTypes.arrayOf()
- 하다를 통해서 .
propValue[key].type !== Card
- 치환 사용
${Card.name}
Library react-element-proptypes는 이 기능을 구현합니다.ElementPropTypes.elementOfType()
:
import ElementPropTypes from "react-element-proptypes";
class CardGroup extends Component {
static propTypes = {
children: PropTypes.arrayOf(ElementPropTypes.elementOfType(Card))
}
// ...
}
간단하고 생산성이 뛰어난 체크.Card Group 컴포넌트 상부에 있는 다음 작업을 수행합니다.
const cardType = (<Card />).type;
그런 다음, 아이에 대해 반복할 때:
React.children.map(child => child.type === cardType ? child : null);
가 드러나지컴포넌트/하여 with서서서서서/서 an an an an an an an an an an an an an an an an an an an an an an an an an an an an an an an를 만들 수 있다는 것입니다.이 컴포넌트는 필요한 클래스를 공개하지 않고instanceof
을을확확확확
유형을 확인합니다.
props.children.forEach(child =>
console.assert(
child.type.name == "CanvasItem",
"CanvasScroll can only have CanvasItem component as children."
)
)
이 투고와 관련하여, 저는 비슷한 문제를 발견했습니다.아이가 Tooltip 컴포넌트의 여러 아이콘 중 하나일 경우 오류를 발생시켜야 했습니다.
// 아이콘/index.ts
export {default as AddIcon} from './AddIcon';
export {default as SubIcon} from './SubIcon';
...
// 컴포넌트/Tooltip.tsx
import { Children, cloneElement, isValidElement } from 'react';
import * as AllIcons from 'common/icons';
...
const Tooltip = ({children, ...rest}) => {
Children.forEach(children, child => {
// ** Inspired from this post
const reactNodeIsOfIconType = (node, allIcons) => {
const iconTypes = Object.values(allIcons);
return iconTypes.some(type => typeof node === 'object' && node !== null && node.type === type);
};
console.assert(!reactNodeIsOfIconType(child, AllIcons),'Use some other component instead...')
})
...
return Children.map(children, child => {
if (isValidElement(child) {
return cloneElement(child, ...rest);
}
return null;
});
}
언급URL : https://stackoverflow.com/questions/27366077/only-allow-children-of-a-specific-type-in-a-react-component
'programing' 카테고리의 다른 글
제약 조건의 이름을 모를 때 Oracle에서 "not null" 제약 조건을 삭제하려면 어떻게 해야 합니까? (0) | 2023.03.21 |
---|---|
Wait는 비동기 함수 내부의 예약된 단어 오류입니다. (0) | 2023.03.21 |
변경에 대한 AngularJS $watch 루트 범위 변수 (0) | 2023.03.21 |
Jquery asp.net 버튼클릭 이벤트 via ajax (0) | 2023.03.21 |
Html 요소 없이 AngularJs ng-repeat (0) | 2023.03.21 |