Reactã®ChildrenãŠãŒãã£ãªãã£ã掻çšããåèŠçŽ ãå¹ççã«æäœã»å埩ããæ¹æ³ãæ¢ããŸããåçã§ã¹ã±ãŒã©ãã«ãªReactã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®ãã¹ããã©ã¯ãã£ã¹ãšé«åºŠãªãã¯ããã¯ãåŠã³ãŸãããã
React ChildrenãŠãŒãã£ãªãã£ã®å®å šãã¹ã¿ãŒã¬ã€ã
Reactã®ã³ã³ããŒãã³ãã¢ãã«ã¯éåžžã«åŒ·åã§ãéçºè
ã¯åå©çšå¯èœãªæ§æèŠçŽ ããè€éãªUIãæ§ç¯ã§ããŸãããã®äžå¿ã«ããã®ããchildrenãã®æŠå¿µã§ããããã¯ãã³ã³ããŒãã³ãã®éå§ã¿ã°ãšçµäºã¿ã°ã®éã«æž¡ãããèŠçŽ ã®ããšã§ããäžèŠã·ã³ãã«ã«èŠããŸããããããã®childrenã广çã«ç®¡çã»æäœããããšã¯ãåçã§æè»ãªã¢ããªã±ãŒã·ã§ã³ãäœæããäžã§æ¥µããŠéèŠã§ããReactã¯ããã®ç®çã®ããã«ç¹å¥ã«èšèšãããReact.Children APIã®äžã«äžé£ã®ãŠãŒãã£ãªãã£ãæäŸããŠããŸãããã®ç·åã¬ã€ãã§ã¯ããããã®ãŠãŒãã£ãªãã£ãè©³çŽ°ã«æ¢ããReactã§ã®åèŠçŽ ã®æäœãšå埩ããã¹ã¿ãŒããããã®å®è·µçãªäŸãšãã¹ããã©ã¯ãã£ã¹ãæäŸããŸãã
React Childrenãçè§£ãã
Reactã§ã¯ããchildrenããšã¯ãã³ã³ããŒãã³ããéå§ã¿ã°ãšçµäºã¿ã°ã®éã§åãåãã³ã³ãã³ããæããŸãããã®ã³ã³ãã³ãã¯ãåçŽãªããã¹ãããè€éãªã³ã³ããŒãã³ãéå±€ãŸã§ããããããã®ã«ãªãåŸãŸããæ¬¡ã®äŸãèããŠã¿ãŸãããïŒ
<MyComponent>
<p>This is a child element.</p>
<AnotherComponent />
</MyComponent>
MyComponentã®å
éšã§ã¯ãprops.childrenããããã£ã«ããã2ã€ã®èŠçŽ ãå«ãŸããŸãïŒ<p>èŠçŽ ãš<AnotherComponent />ã€ã³ã¹ã¿ã³ã¹ã§ããããããprops.childrenã«çŽæ¥ã¢ã¯ã»ã¹ããŠæäœããããšã¯ãç¹ã«è€éãªæ§é ãæ±ãå Žåã«ããªãããŒã«ãªãå¯èœæ§ããããŸããããã§React.ChildrenãŠãŒãã£ãªãã£ã®åºçªã§ãã
React.Children APIïŒåèŠçŽ ç®¡çã®ããã®ããŒã«ããã
React.Children APIã¯ãäžéæãªããŒã¿æ§é ã§ããprops.childrenãå埩åŠçãã倿ããããã®äžé£ã®éçã¡ãœãããæäŸããŸãããããã®ãŠãŒãã£ãªãã£ã¯ãprops.childrenã«çŽæ¥ã¢ã¯ã»ã¹ãããããå
ç¢ã§æšæºåãããæ¹æ³ã§childrenãæ±ãææ®µãæäŸããŸãã
1. React.Children.map(children, fn, thisArg?)
React.Children.map()ã¯ãããããæãé »ç¹ã«äœ¿çšããããŠãŒãã£ãªãã£ã§ããããã¯ãæšæºã®JavaScriptã®Array.prototype.map()ã¡ãœããã«äŒŒãŠããŸããchildren propã®åçŽæ¥ã®åãå埩åŠçããæäŸããã颿°ãååã«é©çšããŸããçµæã¯ã倿ãããchildrenãå«ãæ°ããã³ã¬ã¯ã·ã§ã³ïŒéåžžã¯é
åïŒã«ãªããŸããéèŠãªã®ã¯ãå«ãããããæ·±ãéå±€ã®åå«ã§ã¯ãªãã*çŽæ¥ã®*åã«ã®ã¿äœçšããç¹ã§ãã
äŸïŒãã¹ãŠã®çŽæ¥ã®åã«å ±éã®ã¯ã©ã¹åã远å ãã
function MyComponent(props) {
return (
<div className="my-component">
{React.Children.map(props.children, (child) => {
// React.isValidElement()ã¯ãåãæååãæ°å€ã®å Žåã®ãšã©ãŒãé²ããŸãã
if (React.isValidElement(child)) {
return React.cloneElement(child, {
className: child.props.className ? child.props.className + ' common-class' : 'common-class',
});
} else {
return child;
}
})}
</div>
);
}
// äœ¿çšæ³:
<MyComponent>
<div className="existing-class">Child 1</div>
<span>Child 2</span>
</MyComponent>
ãã®äŸã§ã¯ãReact.Children.map()ãMyComponentã®åãå埩åŠçããŸããååã«å¯ŸããŠãReact.cloneElement()ã䜿çšããŠèŠçŽ ãã¯ããŒã³ãããcommon-classããšããã¯ã©ã¹åã远å ããŸããæçµçãªåºåã¯æ¬¡ã®ããã«ãªããŸãïŒ
<div className="my-component">
<div className="existing-class common-class">Child 1</div>
<span className="common-class">Child 2</span>
</div>
React.Children.map()ã®éèŠãªèæ
®äºé
ïŒ
- key prop: åããããããŠæ°ããèŠçŽ ãè¿ãéã¯ãåžžã«åèŠçŽ ã«äžæã®
keypropãããããšã確èªããŠãã ãããããã«ãããReactã¯DOMãå¹ççã«æŽæ°ã§ããŸãã nullãè¿ã: ãããã³ã°é¢æ°ããnullãè¿ãããšã§ãç¹å®ã®åããã£ã«ã¿ãªã³ã°ã§ããŸãã- èŠçŽ ã§ãªãåã®åŠç: childrenã¯æååãæ°å€ããããã¯
null/undefinedã§ããå¯èœæ§ããããŸããReact.isValidElement()ã䜿çšããŠãReactèŠçŽ ã®ã¿ãã¯ããŒã³ããã³å€æŽããŠããããšã確èªããŠãã ããã
2. React.Children.forEach(children, fn, thisArg?)
React.Children.forEach()ã¯React.Children.map()ã«äŒŒãŠããŸãããæ°ããã³ã¬ã¯ã·ã§ã³ãè¿ããŸããã代ããã«ãåã«childrenãå埩åŠçããååã«å¯ŸããŠæäŸããã颿°ãå®è¡ããŸããããã¯ãå¯äœçšãå®è¡ããããchildrenã«é¢ããæ
å ±ãåéãããããããã«ãã䜿çšãããŸãã
äŸïŒchildrenå ã®<li>èŠçŽ ã®æ°ãæ°ãã
function MyComponent(props) {
let liCount = 0;
React.Children.forEach(props.children, (child) => {
if (child && child.type === 'li') {
liCount++;
}
});
return (
<div>
<p>Number of <li> elements: {liCount}</p>
{props.children}
</div>
);
}
// äœ¿çšæ³:
<MyComponent>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<p>Some other content</p>
</MyComponent>
ãã®äŸã§ã¯ãReact.Children.forEach()ãchildrenãå埩åŠçããèŠã€ãã£ãå<li>èŠçŽ ã«å¯ŸããŠliCountãã€ã³ã¯ãªã¡ã³ãããŸãããã®åŸãã³ã³ããŒãã³ãã¯<li>èŠçŽ ã®æ°ãã¬ã³ããªã³ã°ããŸãã
React.Children.map()ãšReact.Children.forEach()ã®äž»ãªéãïŒ
React.Children.map()ã¯å€æŽãããåã®æ°ããé åãè¿ããŸãããReact.Children.forEach()ã¯äœãè¿ããŸãããReact.Children.map()ã¯éåžžãåã®å€æã«äœ¿çšãããReact.Children.forEach()ã¯å¯äœçšãæ å ±åéã«äœ¿çšãããŸãã
3. React.Children.count(children)
React.Children.count()ã¯ãchildren propå
ã®çŽæ¥ã®åã®æ°ãè¿ããŸããããã¯ãåã®ã³ã¬ã¯ã·ã§ã³ã®ãµã€ãºã決å®ããããã®ã·ã³ãã«ã§äŸ¿å©ãªãŠãŒãã£ãªãã£ã§ãã
äŸïŒåã®æ°ã衚瀺ãã
function MyComponent(props) {
const childCount = React.Children.count(props.children);
return (
<div>
<p>This component has {childCount} children.</p>
{props.children}
</div>
);
}
// äœ¿çšæ³:
<MyComponent>
<div>Child 1</div>
<span>Child 2</span>
<p>Child 3</p>
</MyComponent>
ãã®äŸã§ã¯ãMyComponentã«3ã€ã®çŽæ¥ã®åãæž¡ãããŠãããããReact.Children.count()ã¯3ãè¿ããŸãã
4. React.Children.toArray(children)
React.Children.toArray()ã¯ãchildren propïŒäžéæãªããŒã¿æ§é ïŒãæšæºã®JavaScripté
åã«å€æããŸããããã¯ããœãŒãããã£ã«ã¿ãªã³ã°ãªã©ãåã«å¯ŸããŠé
ååºæã®æäœãå®è¡ããå¿
èŠãããå Žåã«äŸ¿å©ã§ãã
äŸïŒåã®é åºãéã«ãã
function MyComponent(props) {
const childrenArray = React.Children.toArray(props.children);
const reversedChildren = childrenArray.reverse();
return (
<div>
{reversedChildren}
</div>
);
}
// äœ¿çšæ³:
<MyComponent>
<div>Child 1</div>
<span>Child 2</span>
<p>Child 3</p>
</MyComponent>
ãã®äŸã§ã¯ãReact.Children.toArray()ãåãé
åã«å€æããŸãããã®åŸãé
åã¯Array.prototype.reverse()ã䜿çšããŠéé ã«ãããéé ã«ãªã£ãåãã¬ã³ããªã³ã°ãããŸãã
React.Children.toArray()ã®éèŠãªèæ
®äºé
ïŒ
- çµæã®é åã§ã¯ãå ã®ããŒããæŽŸçããããèªåçã«çæãããããŒãåèŠçŽ ã«å²ãåœãŠãããŸããããã«ãããé åæäœåŸã§ãReactãå¹ççã«DOMãæŽæ°ã§ããããã«ãªããŸãã
- ä»»æã®é åæäœãå®è¡ã§ããŸãããæ³šæããªããšãchildrené åãçŽæ¥å€æŽãããšäºæããªãåäœã«ã€ãªããå¯èœæ§ãããããšãå¿ããªãã§ãã ããã
é«åºŠãªãã¯ããã¯ãšãã¹ããã©ã¯ãã£ã¹
1. åã®å€æŽã«React.cloneElement()ã䜿çšãã
åèŠçŽ ã®ããããã£ã倿Žããå¿
èŠãããå Žåã¯ãäžè¬çã«React.cloneElement()ã䜿çšããããšãæšå¥šãããŸãããã®é¢æ°ã¯ãæ¢åã®èŠçŽ ã«åºã¥ããŠæ°ããReactèŠçŽ ãäœæããå
ã®èŠçŽ ãçŽæ¥å€æŽããããšãªãæ°ããpropsãäžæžããŸãã¯è¿œå ã§ããŸããããã«ãããäžå€æ§ãç¶æãããäºæããªãå¯äœçšã鲿¢ãããŸãã
äŸïŒãã¹ãŠã®åã«ç¹å®ã®propã远å ãã
function MyComponent(props) {
return (
<div>
{React.Children.map(props.children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, { customProp: 'Hello from MyComponent' });
} else {
return child;
}
})}
</div>
);
}
// äœ¿çšæ³:
<MyComponent>
<div>Child 1</div>
<span>Child 2</span>
</MyComponent>
ãã®äŸã§ã¯ãReact.cloneElement()ã䜿çšããŠãååèŠçŽ ã«customPropã远å ããŠããŸããçµæã®èŠçŽ ã¯ããã®propsãªããžã§ã¯ãå
ã§ãã®propãå©çšã§ããããã«ãªããŸãã
2. ãã©ã°ã¡ã³ãåãããåã® Ø§ÙØªØ¹Ø§Ù Ù
Reactãã©ã°ã¡ã³ãïŒ<></>ãŸãã¯<React.Fragment></React.Fragment>ïŒã䜿çšãããšãäœåãªDOMããŒãã远å ããã«è€æ°ã®åãã°ã«ãŒãåã§ããŸããReact.ChildrenãŠãŒãã£ãªãã£ã¯ãã©ã°ã¡ã³ããé©åã«åŠçãããã©ã°ã¡ã³ãå
ã®ååãå¥ã
ã®åãšããŠæ±ããŸãã
äŸïŒãã©ã°ã¡ã³ãå ã®åãå埩åŠçãã
function MyComponent(props) {
React.Children.forEach(props.children, (child) => {
console.log(child);
});
return <div>{props.children}</div>;
}
// äœ¿çšæ³:
<MyComponent>
<>
<div>Child 1</div>
<span>Child 2</span>
</>
<p>Child 3</p>
</MyComponent>
ãã®äŸã§ã¯ãReact.Children.forEach()颿°ã¯3ã€ã®åãå埩åŠçããŸãïŒ<div>èŠçŽ ã<span>èŠçŽ ãããã³<p>èŠçŽ ã§ããæåã®2ã€ããã©ã°ã¡ã³ãã§ã©ãããããŠããã«ããããããããã®ããã«ãªããŸãã
3. ããŸããŸãªåã¿ã€ãã®åŠç
åè¿°ã®ããã«ãchildrenã¯ReactèŠçŽ ãæååãæ°å€ããããã¯null/undefinedã§ããå¯èœæ§ããããŸããReact.ChildrenãŠãŒãã£ãªãã£é¢æ°å
ã§ãããã®ç°ãªãã¿ã€ããé©åã«åŠçããããšãéèŠã§ããReact.isValidElement()ã䜿çšããããšã¯ãReactèŠçŽ ãšä»ã®ã¿ã€ããåºå¥ããããã«äžå¯æ¬ ã§ãã
äŸïŒåã®ã¿ã€ãã«åºã¥ããŠç°ãªãã³ã³ãã³ããã¬ã³ããªã³ã°ãã
function MyComponent(props) {
return (
<div>
{React.Children.map(props.children, (child) => {
if (React.isValidElement(child)) {
return <div className="element-child">{child}</div>;
} else if (typeof child === 'string') {
return <div className="string-child">String: {child}</div>;
} else if (typeof child === 'number') {
return <div className="number-child">Number: {child}</div>;
} else {
return null;
}
})}
</div>
);
}
// äœ¿çšæ³:
<MyComponent>
<div>Child 1</div>
"This is a string child"
123
</MyComponent>
ãã®äŸã¯ãç¹å®ã¯ã©ã¹åã§ã¬ã³ããªã³ã°ããããšã§ãããŸããŸãªåã®ã¿ã€ããåŠçããæ¹æ³ã瀺ããŠããŸããåãReactèŠçŽ ã®å Žåããelement-childãã¯ã©ã¹ãæã€<div>ã§ã©ãããããŸããæååã®å Žåã¯ãstring-childãã¯ã©ã¹ãæã€<div>ã§ã©ããããã以äžåæ§ã§ãã
4. åã®æ·±ããã©ããŒãµã«ïŒæ³šæããŠäœ¿çšïŒïŒ
React.ChildrenãŠãŒãã£ãªãã£ã¯çŽæ¥ã®åã«ã®ã¿äœçšããŸããã³ã³ããŒãã³ãããªãŒå
šäœïŒå«ãããããæ·±ãéå±€ã®åå«ãå«ãïŒããã©ããŒã¹ããå¿
èŠãããå Žåã¯ãååž°çãªãã©ããŒãµã«é¢æ°ãå®è£
ããå¿
èŠããããŸãããã ããããã¯èšç®ã³ã¹ããé«ããã³ã³ããŒãã³ãæ§é ã®èšèšäžã®æ¬ é¥ã瀺ããŠããå¯èœæ§ããããããå®è¡ããéã¯éåžžã«æ³šæããŠãã ããã
äŸïŒåã®ååž°çãªãã©ããŒãµã«
function traverseChildren(children, callback) {
React.Children.forEach(children, (child) => {
callback(child);
if (React.isValidElement(child) && child.props.children) {
traverseChildren(child.props.children, callback);
}
});
}
function MyComponent(props) {
traverseChildren(props.children, (child) => {
console.log(child);
});
return <div>{props.children}</div>;
}
// äœ¿çšæ³:
<MyComponent>
<div>
<span>Child 1</span>
<p>Child 2</p>
</div>
<p>Child 3</p>
</MyComponent>
ãã®äŸã§ã¯ãåãååž°çã«å埩åŠçããtraverseChildren()颿°ãå®çŸ©ããŠããŸããååã«å¯ŸããŠæäŸãããã³ãŒã«ããã¯ãåŒã³åºãããã®åŸãèªèº«ã®åãæã€åã«å¯ŸããŠååž°çã«èªèº«ãåŒã³åºããŸããç¹°ãè¿ãã«ãªããŸããããã®ã¢ãããŒãã¯æ
éã«äœ¿çšãã絶察ã«å¿
èŠãªå Žåã«ã®ã¿äœ¿çšããŠãã ãããæ·±ããã©ããŒãµã«ãé¿ãã代æ¿ã®ã³ã³ããŒãã³ãèšèšãæ€èšããŠãã ããã
åœéåïŒi18nïŒãšReact Children
ã°ããŒãã«ãªãªãŒãã£ãšã³ã¹åãã®ã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããéã«ã¯ãReact.ChildrenãŠãŒãã£ãªãã£ãåœéåã©ã€ãã©ãªãšã©ã®ããã«çžäºäœçšããããèæ
®ããŠãã ãããããšãã°ãreact-intlãi18nextã®ãããªã©ã€ãã©ãªã䜿çšããŠããå ŽåãããŒã«ã©ã€ãºãããæååãæ£ããã¬ã³ããªã³ã°ãããããã«ãåããããããæ¹æ³ã調æŽããå¿
èŠããããããããŸããã
äŸïŒreact-intlãReact.Children.map()ãšå
±ã«äœ¿çšãã
import { FormattedMessage } from 'react-intl';
function MyComponent(props) {
return (
<div>
{React.Children.map(props.children, (child, index) => {
if (typeof child === 'string') {
// æååã®åãFormattedMessageã§ã©ãããã
return <FormattedMessage id={`myComponent.child${index + 1}`} defaultMessage={child} />;
} else {
return child;
}
})}
</div>
);
}
// ãã±ãŒã«ãã¡ã€ã«ïŒäŸïŒen.json, ja.jsonïŒã§ç¿»èš³ãå®çŸ©ããŸã:
// {
// "myComponent.child1": "翻蚳ãããå 1",
// "myComponent.child2": "翻蚳ãããå 2"
// }
// äœ¿çšæ³:
<MyComponent>
"Child 1"
<div>Some element</div>
"Child 2"
</MyComponent>
ãã®äŸã¯ãreact-intlã®<FormattedMessage>ã³ã³ããŒãã³ãã§æååã®åãã©ããããæ¹æ³ã瀺ããŠããŸããããã«ããããŠãŒã¶ãŒã®ãã±ãŒã«ã«åºã¥ããŠæååã®åã®ããŒã«ã©ã€ãºãããããŒãžã§ã³ãæäŸã§ããŸãã<FormattedMessage>ã®id propã¯ããã±ãŒã«ãã¡ã€ã«å
ã®ããŒã«å¯Ÿå¿ããå¿
èŠããããŸãã
äžè¬çãªäœ¿çšäŸ
- ã¬ã€ã¢ãŠãã³ã³ããŒãã³ãïŒä»»æã®å 容ãåãšããŠåãå ¥ããããšãã§ããåå©çšå¯èœãªã¬ã€ã¢ãŠãã³ã³ããŒãã³ãã®äœæã
- ã¡ãã¥ãŒã³ã³ããŒãã³ãïŒã³ã³ããŒãã³ãã«æž¡ãããåã«åºã¥ããŠã¡ãã¥ãŒé ç®ãåçã«çæããã
- ã¿ãã³ã³ããŒãã³ãïŒã¢ã¯ãã£ããªã¿ãã管çããéžæãããåã«åºã¥ããŠå¯Ÿå¿ããã³ã³ãã³ããã¬ã³ããªã³ã°ããã
- ã¢ãŒãã«ã³ã³ããŒãã³ãïŒåãã¢ãŒãã«åºæã®ã¹ã¿ã€ãªã³ã°ãšæ©èœã§ã©ããããã
- ãã©ãŒã ã³ã³ããŒãã³ãïŒãã©ãŒã ãã£ãŒã«ããå埩åŠçããå ±éã®æ€èšŒãã¹ã¿ã€ãªã³ã°ãé©çšããã
çµè«
React.Children APIã¯ãReactã³ã³ããŒãã³ãå
ã®åèŠçŽ ã管çããã³æäœããããã®åŒ·åãªããŒã«ã»ããã§ãããããã®ãŠãŒãã£ãªãã£ãçè§£ãããã®ã¬ã€ãã§æŠèª¬ãããã¹ããã©ã¯ãã£ã¹ãé©çšããããšã§ãããæè»ã§ãåå©çšå¯èœã§ãä¿å®ããããã³ã³ããŒãã³ããäœæã§ããŸãããããã®ãŠãŒãã£ãªãã£ã¯è³¢æã«äœ¿çšããç¹ã«å€§èŠæš¡ãªã³ã³ããŒãã³ãããªãŒãæ±ãéã«ã¯ãè€éãªåã®æäœãããã©ãŒãã³ã¹ã«äžãã圱é¿ãåžžã«èæ
®ããŠãã ãããReactã®ã³ã³ããŒãã³ãã¢ãã«ã®åãæŽ»çšããã°ããŒãã«ãªãªãŒãã£ãšã³ã¹åãã®çŽ æŽããããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ãæ§ç¯ããŸãããïŒ
ãããã®ãã¯ããã¯ããã¹ã¿ãŒããããšã§ãããå ç¢ã§é©å¿æ§ã®é«ãReactã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸããéçºããã»ã¹ã§ã¯ãã³ãŒãã®æçããããã©ãŒãã³ã¹ãä¿å®æ§ãåªå ããããšãå¿ããªãã§ãã ãããããããŒã³ãŒãã£ã³ã°ïŒ