ä»æ¥ã¯Reactã®key
å±æ§ã«ã€ããŠè©±ããŸãããã å€ãã®å ŽåãReactã䜿çšãå§ããã°ããã®éçºè
ã¯ã key
å±æ§ãããŸãéèŠããŸããã ããããç¡é§ã«...

ããªããéµã䜿çšããŠããªãããšãããã£ããšãã«ã¢ãã«ãèšãããš
ããŒãå®å
šã«ç°ãªãã±ãŒã¹ã§æ瀺ããã«ã¯ãèšç»ãæ€èšããŠãã ããã
- å解
- ããŒã®åå©çšãšæ£èŠå
- åäžã®ã¢ã€ãã ãã¬ã³ããªã³ã°ãããšãã«ããŒã䜿çšãã
- åã«æž¡ããšãã«ããŒãæäœãã
å€ãã®è³æãããã®ã§ãåããŒãã®çµããã«çµè«ããããŸãã èšäºã®æåŸã«ãäžè¬çãªçµè«ã瀺ãããŠããããããã«ã€ããŠç°¡åã«èª¬æããŸãã ã³ãŒãã¯ãcodesandboxã®äŸãšãã¿ãã¬ã®äž¡æ¹ã§èŠãããšãã§ããŸãã
å解
åå¿ã«ãããããŒã®äž»ãªã¿ã¹ã¯ã¯ã調æŽã¡ã«ããºã ãæ¯æŽããããšã§ãã ååã®ãªã¹ããã¬ã³ããªã³ã°ããå°ããªã³ã³ããŒãã³ããäœæããŸãããïŒ
import React from "react"; import { render } from "react-dom"; class App extends React.Component { state = { names: ["", "", ""] }; render() { return <Names names={this.state.names} />; } } class Names extends React.PureComponent { render() { return (<ul>{this.props.names.map(name => <Name>{name}</Name>)}</ul>); } } class Name extends React.PureComponent { render() { return (<li>{this.props.children}</li>); } } render(<App />, document.getElementById("root"));
ããŒãæå®ããŸããã§ããã ã³ã³ãœãŒã«ã«æ¬¡ã®ã¡ãã»ãŒãžã衚瀺ãããŸãã
èŠåïŒé
åãŸãã¯ã€ãã¬ãŒã¿ã®ååã«ã¯ãäžæã®ãããŒããããããå¿
èŠã§ãã
ããã§ãã¿ã¹ã¯ãè€éã«ãããã¿ã³ã䜿çšããŠå
¥åãäœæããæ°ããååãæåãšæåŸã«è¿œå ããŸãã ããã«ã componentDidUpdate
ã®ååã®å€æŽãã°ãcomponentDidUpdate
ããã³DidMount
è¿œå ããåã瀺ããŸãã
ãªã¹ãã«ã¢ã€ãã ãè¿œå ãã import React, { Component, PureComponent, Fragment } from "react"; import { render } from "react-dom"; class App extends Component { state = { names: ["", "", ""] }; addTop = name => { this.setState(state => ({ names: [name, ...state.names] })); }; addBottom = name => { this.setState(state => ({ names: [...state.names, name] })); }; render() { return ( <Fragment> <Names names={this.state.names} /> <AddName addTop={this.addTop} addBottom={this.addBottom} /> </Fragment> ); } } class AddName extends PureComponent { getInput = el => { this.input = el; }; addToTop = () => { if (!this.input.value.trim()) { return; } this.props.addTop(this.input.value); this.input.value = ""; }; addToBottom = () => { if (!this.input.value.trim()) { return; } this.props.addBottom(this.input.value); this.input.value = ""; }; render() { return ( <Fragment> <input ref={this.getInput} /> <button onClick={this.addToTop}>Add to TOP</button> <button onClick={this.addToBottom}>Add to BOTTOM</button> </Fragment> ); } } class Names extends PureComponent { render() { return <ul>{this.props.names.map(name => <Name>{name}</Name>)}</ul>; } } class Name extends PureComponent { componentDidMount() { console.log(`Mounted with ${this.props.children}`); } componentDidUpdate(prevProps) { console.log(`Updated from ${prevProps.children} to ${this.props.children}`); } render() { return <li>{this.props.children}</li>; } } render(<App />, document.getElementById("root"));
ãªã¹ãã®æåŸã«ãããžã«ããè¿œå ããŠãããå
é ã«ãããŒã«ããè¿œå ããŠãã ããã ã³ã³ãœãŒã«ã«æ³šæããŠãã ããã Codesandboxã§ã¯ããã¿ã³ãã¯ãªãã¯ããŠè¡šç€ºãïŒäžããäžå€®ã«ïŒå€æŽããããšã«ããããœãŒã¹ã³ãŒããéãããšãã§ããŸãã
åæ§ã®ãªã¹ãã®äœæ¥ã®ãã¢ã³ã¹ãã¬ãŒã·ã§ã³ïŒ
äžããèŠçŽ ãè¿œå ãããšãNameã³ã³ããŒãã³ããåæç»ãããæ°ããã³ã³ããŒãã³ããchildren ===
äœæãããç¶æ³ã«ãªããŸãïŒ
MishaããPavelã«æŽæ°ãããŸãã
ãããšã«ããããŒã·ã£ã«æŽæ°
ããªãŒããããããšã«ã«æŽæ°
VasilyããMarinaã«æŽæ°ãããŸãã
Vasilyã§ããŠã³ã
ãªããããèµ·ãã£ãŠããã®ã§ããïŒ èª¿æŽã¡ã«ããºã ãèŠãŠã¿ãŸãããã
1ã€ã®ããªãŒããå¥ã®ããªãŒãžã®å®å
šãªèª¿æŽãšçž®å°ã¯ãã¢ã«ãŽãªãºã ã®è€éãOïŒn³ïŒã䌎ãé«äŸ¡ãªã¿ã¹ã¯ã§ãã ããã¯ã倧éã®å
çŽ ã§ã¯åå¿ãé
ãããšãæå³ããŸãã
ãã®ãããVDOM調æŽã¡ã«ããºã ã¯ã次ã®åçŽåïŒã«ãŒã«ïŒã䜿çšããŠæ©èœããŸãã
1ïŒç°ãªãã¿ã€ãã®2ã€ã®èŠçŽ ã¯ç°ãªããµãããªãŒãçæããŸããã€ãŸããèŠçŽ ã¿ã€ãã<div>
ãã<section>
ãŸãã¯å¥ã®ã¿ã°ã«å€æŽãããšãreactã¯<div>
ãš<section>
å
ã®ãµãããªãŒãç°ãªããšèŠãªããŸãã ãã®åå¿ã«ããã div
å
ã«ãã£ãèŠçŽ ãåé€ãããã»ã¯ã·ã§ã³å
ã®ãã¹ãŠã®èŠçŽ ãããŠã³ããããŸãã ã¿ã°èªäœãå€æŽãããå Žåã§ãã ããªãŒã®åé€ãšåæåã®åæ§ã®ç¶æ³ã¯ã1ã€ã®åå¿ã³ã³ããŒãã³ããå¥ã®åå¿ã³ã³ããŒãã³ãã«å€æŽããããšãã«çºçããŸãããã³ã³ãã³ãèªäœã¯åãããã«èŠããŸããïŒããã¯èª€è§£ã«ãããŸããïŒã
oldTree: <div> <MyComponent /> </div>
Reactã³ã³ããŒãã³ãã§ãåæ§ã«æ©èœããŸãã
2ïŒèŠçŽ ã®é
åã¯èŠçŽ ããšã«æ¯èŒãããŸããã€ãŸããåå¿ã¯2ã€ã®é
åã«å¯ŸããŠåæã«ç¹°ãè¿ãããèŠçŽ ããã¢ã§æ¯èŒããŸãã ãããã£ãŠãäžèšã®ååãæã€äŸã®ãªã¹ãã®ãã¹ãŠã®èŠçŽ ãåæç»ããŸããã äŸãèŠãŠã¿ãŸãããïŒ
åå¿ã¯ãæåã«<li></li>
ãæ¯èŒãã次ã«<li></li>
ãæ¯èŒããæçµçã«<li></li>
å€ãããªãŒã«ãªãããšãæ€åºããŸãã ãããŠããã®èŠçŽ ãäœæããŸãã
èŠçŽ ãè¿œå ããå ŽåïŒ
Reactã¯<li></li>
ãš<li></li>
ãæ¯èŒããæŽæ°ããŸãã 次ã«ã <li></li>
ãš<li></li>
æ¯èŒããæŽæ°ããŠãæåŸã«<li></li>
ãŸãã èŠçŽ ãå
é ã«æ¿å
¥ããããšãreactã¯é
åå
ã®ãã¹ãŠã®èŠçŽ ãæŽæ°ããŸãã
åé¡ã解決ããããã«ãéèŠãªå±æ§ãåå¿ã«äœ¿çšãããŸãã ããŒãè¿œå ããããšãreactã¯èŠçŽ ã次ã
ãšæ¯èŒããŸããããããŒã®å€ã§æ€çŽ¢ããŸãã ã¬ã³ããªã³ã°åã䜿çšããäŸã¯ãããçç£çã«ãªããŸãã
reactã¯key='1'
ã key='2'
ãèŠã€ãããããã«å€æŽãçºçããŠããªããšå€æããæ°ãã<li key='3'></li>
èŠçŽ <li key='3'></li>
ãèŠã€ããŠããã ããè¿œå ããŸãã ãããã£ãŠãããŒã䜿çšãããšãreactã¯1ã€ã®ã³ã³ããŒãã³ãã®ã¿ãæŽæ°ããŸãã
ããŒãè¿œå ããŠãäŸãæžãæããŸãã ãªã¹ãã®äžçªäžã«èŠçŽ ãè¿œå ãããšã1ã€ã®ã³ã³ããŒãã³ãã®ã¿ãäœæãããããšã«æ³šæããŠãã ããã
é
åå
ã®èŠçŽ ã®ã€ã³ããã¯ã¹ãããŒãšããŠäœ¿çšããã«ãååã«idãè¿œå ããããŒãçŽæ¥ç®¡çããŠããããšã«æ³šæããŠãã ããã ããã¯ããªã¹ãã®å
é ã«ååãè¿œå ãããšãã€ã³ããã¯ã¹ã移åããããã§ãã
æåã®éšåãèŠçŽããã«ã¯ïŒ
ããŒã¯é
åã®èŠçŽ ã䜿çšããŠäœæ¥ãæé©åããèŠçŽ ã®äžå¿
èŠãªåé€ãšäœæã®æ°ãæžãããŸãã
ããŒã®åå©çšãšæ£èŠå
ã¿ã¹ã¯ãè€éã«ããŸãããã 次ã«ãæœè±¡çãªäººã§ã¯ãªããéçºããŒã ã®ã¡ã³ããŒã®ãªã¹ããäœæããŸãã äŒç€Ÿã«ã¯2ã€ã®ããŒã ããããŸãã ããŒã ã¡ã³ããŒã¯ãããŠã¹ãã¯ãªãã¯ããŠéžæã§ããŸãã ãé¡ãã®åé¡ã解決ããŠã¿ãŸãããã 人ã匷調ããããŒã ãåãæ¿ããããã«ããŠãã ããïŒ
ããŒãè€è£œããéã®å¯äœçš import React, { Component, PureComponent, Fragment } from "react"; import { render } from "react-dom"; import "./style.css"; class App extends Component { state = { active: 1, teams: [ { id: 1, name: "Amazing Team", developers: [ { id: 1, name: "" }, { id: 2, name: "" }, { id: 3, name: "" } ] }, { id: 2, name: "Another Team", developers: [ { id: 1, name: "" }, { id: 2, name: "" }, { id: 3, name: "" } ] } ] }; addTop = name => { this.setState(state => ({ teams: state.teams.map( team => team.id === state.active ? { ...team, developers: [ { id: team.developers.length + 1, name }, ...team.developers ] } : team ) })); }; addBottom = name => { this.setState(state => ({ teams: state.teams.map( team => team.id === state.active ? { ...team, developers: [ ...team.developers, { id: team.developers.length + 1, name } ] } : team ) })); }; toggle = id => { this.setState(state => ({ teams: state.teams.map( team => team.id === state.active ? { ...team, developers: team.developers.map( developer => developer.id === id ? { ...developer, highlighted: !developer.highlighted } : developer ) } : team ) })); }; switchTeam = id => { this.setState({ active: id }); }; render() { return ( <Fragment> <TeamsSwitcher onSwitch={this.switchTeam} teams={this.state.teams} /> <Users onClick={this.toggle} names={ this.state.teams.find(team => team.id === this.state.active) .developers } /> <AddName addTop={this.addTop} addBottom={this.addBottom} /> </Fragment> ); } } class TeamsSwitcher extends PureComponent { render() { return ( <ul> {this.props.teams.map(team => ( <li onClick={() => { this.props.onSwitch(team.id); }} key={team.id} > {team.name} </li> ))} </ul> ); } } class AddName extends PureComponent { getInput = el => { this.input = el; }; addToTop = () => { if (!this.input.value.trim()) { return; } this.props.addTop(this.input.value); this.input.value = ""; }; addToBottom = () => { if (!this.input.value.trim()) { return; } this.props.addBottom(this.input.value); this.input.value = ""; }; render() { return ( <Fragment> <input ref={this.getInput} /> <button onClick={this.addToTop}>Add to TOP</button> <button onClick={this.addToBottom}>Add to BOTTOM</button> </Fragment> ); } } class Users extends PureComponent { render() { return ( <ul> {this.props.names.map(user => ( <Name id={user.id} onClick={this.props.onClick} highlighted={user.highlighted} key={user.id} > {user.name} </Name> ))} </ul> ); } } class Name extends PureComponent { render() { return ( <li className={this.props.highlighted ? "highlight" : ""} onClick={() => this.props.onClick(this.props.id)} > {this.props.children} </li> ); } } render(<App />, document.getElementById("root"));
äžå¿«ãªæ©èœã«æ³šæããŠãã ããã人ãéžæããŠããããŒã ãåãæ¿ãããšãéžæãã¢ãã¡ãŒã·ã§ã³åãããŸãããä»ã®ããŒã ã®äººã匷調衚瀺ãããããšã¯ãããŸããã§ããã ãããªã®å°è±¡çãªäŸã¯æ¬¡ã®ãšããã§ãã
äžèŠãªããŒãåå©çšãããšãå¯äœçšãçºçããå¯èœæ§ããããŸããæ°ããã³ã³ããŒãã³ããåé€ããŠäœæããã®ã§ã¯ãªããreactãæŽæ°ãããããã§ãã
ããã¯ãç°ãªããŠãŒã¶ãŒã«åãããŒã䜿çšããããã«çºçããŸãã ãããã£ãŠããã®äŸã§ã¯å¿
é ã§ã¯ãããŸããããè©Šè¬ã¯èŠçŽ ã䜿çšããŸãã ããã«ãæ°ãã人ãè¿œå ãããšè€éãªã³ãŒããçæãããŸãã
äžèšã®ã³ãŒãã«ã¯ããã€ãã®åé¡ããããŸãã
- ããŒã¿ã¯æ£èŠåãããŠãããããããã®åŠçã¯è€éã§ãã
- éçºè
ãšã³ãã£ãã£ãšã®ããŒã®éè€ããããŸãããã®ããããªã¢ã¯ã·ã§ã³ã¯ã³ã³ããŒãã³ããåäœæãããæŽæ°ããŸãã ããã¯å¯äœçšã«ã€ãªãããŸãã
åé¡ã解決ããã«ã¯2ã€ã®æ¹æ³ããããŸãã ç°¡åãªè§£æ±ºçã¯ãéçºè
çšã®è€åããŒã${id }.${id }
ã®åœ¢åŒã§äœæããããšã§ããããã«ãããããŒã暪åã£ãŠå¯äœçšããªããããšãã§ããŸãã
ãã ããããŒã¿ãæ£èŠåãããšã³ãã£ãã£ãçµåããããšã«ãããåé¡ãå
æ¬çã«è§£æ±ºã§ããŸãã ãããã£ãŠãç¶æ
ã³ã³ããŒãã³ãã«ã¯ã teams
ã developers
2ã€ã®ãã£ãŒã«ãããããŸãã developers
ã«ã¯id + name
ããããå«ãŸãã teams
ã«ã¯teams
ããéçºè
ã®ãªã¹ããå«ãŸããŸãã ãã®ãœãªã¥ãŒã·ã§ã³ãå®è£
ããŸãã
class App extends Component { state = { active: 1, nextId: 3, developers: { "1": { name: "" }, "2": { name: "" }, }, teams: [ { id: 1, name: "Amazing Team", developers: [1] }, { id: 2, name: "Another Team", developers: [2] } ] }; addTop = name => {...}; addBottom = name => {...} toggle = id => { this.setState(state => ({ developers: { ...state.developers, [id]: { ...state.developers[id], highlighted: !state.developers[id].highlighted } } })); }; switchTeam = id => {...}; render() {
æ£èŠåãããå®å
šãªãµã³ãã«ã³ãŒã import React, { Component, PureComponent, Fragment } from "react"; import { render } from "react-dom"; import "./style.css"; class App extends Component { state = { active: 1, nextId: 7, developers: { "1": { name: "" }, "2": { name: "" }, "3": { name: "" }, "4": { name: "" }, "5": { name: "" }, "6": { name: "" } }, teams: [ { id: 1, name: "Amazing Team", developers: [1, 2, 3] }, { id: 2, name: "Another Team", developers: [4, 5, 6] } ] }; addTop = name => { this.setState(state => ({ developers: { ...state.developers, [state.nextId]: { name } }, nextId: state.nextId + 1, teams: state.teams.map( team => team.id === state.active ? { ...team, developers: [state.nextId, ...team.developers] } : team ) })); }; addBottom = name => { this.setState(state => ({
ããã§ãèŠçŽ ãæ£ããåŠçãããŸãã
ããŒã¿ã®æ£èŠåã«ãããã¢ããªã±ãŒã·ã§ã³ããŒã¿ã¬ã€ã€ãŒãšã®å¯Ÿè©±ãç°¡çŽ åãããæ§é ãåçŽåãããè€éãã軜æžãããŸãã ããšãã°ããã°ã«é¢æ°ãæ£èŠåãããããŒã¿ãšæ£èŠåãããŠããªãããŒã¿ãšæ¯èŒããŸãã
ãã³ã ïŒããã¯ãšã³ããŸãã¯APIãæ£èŠåãããŠããªã圢åŒã§ããŒã¿ãæäŸããå Žåã httpsïŒ//github.com/paularmstrong/normalizrã§æ£èŠåã§ããŸã
2çªç®ã®éšåãèŠçŽããã«ã¯ïŒ
ããŒã䜿çšããå ŽåãããŒã¿ãå€æŽãããšãã¯ããŒãå€æŽããå¿
èŠãããããšãç解ããããšãéèŠã§ãã ã¬ãã¥ãŒäžã«çºçãããšã©ãŒã®é®®æãªäŸã¯ãé
åå
ã®èŠçŽ ã®ã€ã³ããã¯ã¹ãkey
ãšããŠäœ¿çšããããšã§ãã ããã«ããã人ã
ã®ãªã¹ãã匷調衚瀺ããŠè¡šç€ºããäŸãšããŠèŠããããªå¯äœçšãçããŸãã
ããŒã¿ããã³/ãŸãã¯è€åkey
æ£èŠåã«ãããç®çã®å¹æãå®çŸã§ããŸãã
- ãšã³ãã£ãã£ãå€æŽããããšãããŒã¿ãæŽæ°ãããŸãïŒããšãã°ã匷調衚瀺ãããããå€æŽããããããŸãïŒã
- æå®ããã
key
æã€èŠçŽ ãããååšããªãå Žåãå€ãã€ã³ã¹ã¿ã³ã¹ãåé€ããŸãã - å¿
èŠãªãšãã«æ°ããèŠçŽ ãäœæããŸãã
åäžã®ã¢ã€ãã ãã¬ã³ããªã³ã°ãããšãã«ããŒã䜿çšãã
説æããããã«ã key
ããªãå Žåã®åå¿ã§ã¯ãå€ãããªãŒãšæ°ããããªãŒã®èŠçŽ ããã¢ã§æ¯èŒããŸãã ããŒãããå Žåã¯ãæå®ãããããŒãæã€ç®çã®èŠçŽ ãchildren
ãªã¹ãã§æ€çŽ¢ããŸãã children
ã1ã€ã®èŠçŽ ã®ã¿ã§æ§æãããå Žåã¯ãã«ãŒã«ã®äŸå€ã§ã¯ãããŸããã
å¥ã®äŸãèŠãŠã¿ãŸããã-éç¥ã ç¹å®ã®æéã«éç¥ã1ã€ã ãååšããæ°ç§é衚瀺ãããŠæ¶ãããšããŸãã ãã®ãããªéç¥ãå®è£
ããã®ã¯ç°¡åã§ããã«ãŠã³ã¿ã®æåŸã«ããcomponentDidMount
ã«åŸã£ãŠã«ãŠã³ã¿ãèšå®ããcomponentDidMount
ã¯ãéç¥ã®é衚瀺ãã¢ãã¡ãŒã·ã§ã³åããŸãã次ã«äŸã瀺ããŸãã
class Notification1 extends PureComponent { componentDidMount() { setTimeout(() => { this.element && this.element.classList.add("notification_hide"); }, 3000); } render() { return ( <div ref={el => (this.element = el)} className="notification"> {this.props.children} </div> ); } }
ã¯ãããã®ã³ã³ããŒãã³ãã«ã¯ãã£ãŒãããã¯ããããŸããonClose
ã¯çºçããŸãããããã®ã¿ã¹ã¯ã«ã¯éèŠã§ã¯ãããŸããã
ã·ã³ãã«ãªã³ã³ããŒãã³ããã§ããŸããã
ç¶æ³ãæ³åããŠãã ãã-ãã¿ã³ãã¯ãªãã¯ãããšãåæ§ã®éç¥ã衚瀺ãããŸãã ãŠãŒã¶ãŒã¯åæ¢ããã«ãã¿ã³ãã¯ãªãã¯ããŸããã3ç§ã®éç¥ã®åŸãnotification_hideã¯ã©ã¹ãè¿œå ããããŠãŒã¶ãŒã«ã¯èŠããªããªããŸãïŒ key
䜿çšããªãã£ãå ŽåïŒã
key
ã䜿çšããã«ã³ã³ããŒãã³ãã®åäœãä¿®æ£ããã«ã¯ãlifeCycleã¡ãœããã䜿çšããŠæ£ããæŽæ°ãããNotification2
ã¯ã©ã¹ãäœæããŸãã
class Notification2 extends PureComponent { componentDidMount() { this.subscribeTimeout(); } componentWillReceiveProps(nextProps) { if (nextProps.children !== this.props.children) { clearTimeout(this.timeout); } } componentDidUpdate(prevProps) { if (prevProps.children !== this.props.children) { this.element.classList.remove("notification_hide"); this.subscribeTimeout(); } } subscribeTimeout() { this.timeout = setTimeout(() => { this.element.classList.add("notification_hide"); }, 3000); } render() { return ( <div ref={el => (this.element = el)} className="notification"> {this.props.children} </div> ); } }
ããã§ã¯ãéç¥ã³ã³ãã³ããå€æŽãããå Žåã«ã¿ã€ã ã¢ãŠããåéããããŒã¿ãæŽæ°ãããšãã«notification_hide
ã¯ã©ã¹ãåé€ããã³ãŒããããã«ååŸããŸããã
ãã ããæåã®ã³ã³ããŒãã³ãNotification1
ãšå±æ§key
ã䜿çšããŠãåé¡ã解決ã§ãkey
ã åéç¥ã«ã¯ç¬èªã®äžæã®id
ããããkey
ãšããŠäœ¿çšãkey
ã éç¥ãå€æŽããããšãã«key
ãå€æŽãããå Žåã Notification1
ãåäœæãããŸãã ã³ã³ããŒãã³ãã¯ãå¿
èŠãªããžãã¹ããžãã¯ã«å¯Ÿå¿ããŸãã
ãã®ããã«
ãŸãã«ãåäžã®ã³ã³ããŒãã³ããã¬ã³ããªã³ã°ãããšãã«key
ã䜿çšããããšãæ£åœåãããŸãã key
ã¯ã調æŽã¡ã«ããºã ãã³ã³ããŒãã³ããæ¯èŒããå¿
èŠãããããæ°ããã³ã³ããŒãã³ããïŒããã«ïŒäœæãã䟡å€ãããããç解ããããã®éåžžã«åŒ·åãªæ¹æ³ã§ãã
åã«æž¡ããšãã«ããŒãæäœãã
key
ã®èå³æ·±ãæ©èœã¯ãã³ã³ããŒãã³ãèªäœã§ã¯äœ¿çšã§ããªãããšã§ãã ããã¯ã key
ãspecial prop
ããã§ãã Reactã«ã¯ã key
ãšref
2ã€ã®ç¹å¥ãªprops
ããããŸãã
class TestKey extends Component { render() {
ããã«ãã³ã³ãœãŒã«ã«ã¯èŠåã衚瀺ãããŸãã
èŠåïŒTestKeyïŒ key
ã¯æ¯æ±ã§ã¯ãããŸããã ã¢ã¯ã»ã¹ããããšãããšã undefined
ãè¿ãããŸãã åã³ã³ããŒãã³ãå
ã§åãå€ã«ã¢ã¯ã»ã¹ããå¿
èŠãããå Žåã¯ãå¥ã®ããããã£ãšããŠæž¡ãå¿
èŠããããŸãã ïŒ https://fb.me/react-special-props ïŒ
ãã ãã key
æã€åãã³ã³ããŒãã³ãã«æž¡ãããå Žåãããããšå¯Ÿè©±ã§ããŸããã key
ãã£ãŒã«ãã¯props
ãªããžã§ã¯ãå
ã§ã¯ãªããã³ã³ããŒãã³ãã¬ãã«ã«ãããŸãã
class TestKey extends Component { render() { console.log(this.props.key); return <div>{this.props.key}</div>; } } class TestChildrenKeys extends Component { render() { React.Children.forEach(this.props.children, child => {
ã³ã³ãœãŒã«ã¯ä»¥äžãåºåããŸãïŒ
1
prop1
2
prop2
3
prop3
10
å°éå
·10
èŠçŽãããšïŒ
key
ãšref
ã¯ãreactã®special props
ã§ãã ãããã¯propsãªããžã§ã¯ãã«ã¯å«ãŸãããã³ã³ããŒãã³ãèªäœã®å
éšã§ã¯å©çšã§ããŸããã
children
æž¡ããã芪ã³ã³ããŒãã³ãããchild.key
ãŸãã¯child.ref
ã¢ã¯ã»ã¹ã§ããŸããããããè¡ãå¿
èŠã¯ãããŸããã ãããå¿
èŠãªç¶æ³ã¯ã»ãšãã©ãããŸããã ãã€ã§ãåé¡ãããç°¡åã«ãããè¯ã解決ã§ããŸãã ã³ã³ããŒãã³ãã§ã®åŠçã«key
å¿
èŠãªå Žåkey
ãããšãã°prop id
key
è€è£œããŸãã
ããŒã®ç¯å²ãã³ã³ããŒãã³ãã«æž¡ãããæ¹æ³ãããŒã®æç¡ã«å¿ããŠèª¿æŽã¡ã«ããºã ãã©ã®ããã«å€åãããã調ã¹ãŸããã ãŸããå¯äžã®åã§ããèŠçŽ ã«å¯ŸããããŒã®äœ¿çšãæ€èšããŸããã æåŸã«ãäž»ãªãã€ã³ããã°ã«ãŒãåããŸãã
key
ãªãkey
ã reconciliation
ã¡ã«ããºã ã¯ãçŸåšã®VDOMãšæ°ããVDOMã®éã§ã³ã³ããŒãã³ãããã¢ã§ãã§ãã¯ããŸãã ãã®ãããã€ã³ã¿ãŒãã§ã€ã¹ã®äžå¿
èŠãªåæç»ãå€æ°çºçããã¢ããªã±ãŒã·ã§ã³ã®é床ãäœäžããŸãã
key
è¿œå ããããšã§key
ãã¢ã®key
æ¯èŒãããåãkey
ïŒã¿ã°/ã³ã³ããŒãã³ãåãèæ
®ãããïŒã§ã³ã³ããŒãã³ããæ€çŽ¢ããããšã§reconciliation
ã¡ã«ããºã ãæ¯æŽããŸã-ããã«ãããã€ã³ã¿ãŒãã§ãŒã¹ã®åæç»ã®åæ°ãæžããŸãã åã®ããªãŒã§å€æŽããã/çºçããªãã£ãèŠçŽ ã®ã¿ãæŽæ°/è¿œå ãããŸãã
éè€key
ã衚瀺ãããªãããã«ããŠãã ããã衚瀺ãåãæ¿ãããšãã«ãæ°ããããŒã¿ãããŒãšäžèŽããŸããã ããã«ãããã¢ãã¡ãŒã·ã§ã³ãªã©ã®äžèŠãªå¯äœçšããäžé©åãªèŠçŽ ã®åäœããžãã¯ãçºçããå¯èœæ§ããããŸãã
ãŸãã«ã key
ã1ã€ã®èŠçŽ ã«ã䜿çšãããŸãã ããã«ãããã³ãŒãã®ãµã€ãºãšç解ãæžå°ããŸãã ãããããã®ã¢ãããŒãã®ç¯å²ã¯éãããŠããŸãã
key
ãšref
ã¯ç¹å¥ãªå°éå
·ã§ãã ãããã¯ã³ã³ããŒãã³ãã§ã¯å©çšã§ããã child.props
å©çšã§ããŸããã child.key
ãä»ããŠèŠªã«ã¢ã¯ã»ã¹ã§ããŸãããå®éã«ã¯ããã«å¯Ÿããå®éã®ã¢ããªã±ãŒã·ã§ã³ã¯ãããŸããã åã³ã³ããŒãã³ãã«key
ãå¿
èŠkey
å Žåãæ£ãã解決çã¯ãããšãã°prop id
ã§è€è£œããããšã§ãã