±à¼ÍƼö: |
±¾ÎÄÀ´×ÔÓÚÍøÂ磬Ö÷Òª½éÉÜÁËReact
v16.0 °æ±¾ÖжÔ×îÐ嵀 Context API ºÍ Ref APIµÈ·½ÃæµÄϸ½ÚµÄ½²½â¼°×ܽᣬϣÍû¶Ô´ó¼ÒµÄÑ§Ï°ÄØ¹ýÓаïÖú¡£ |
|

×Ô´ÓÈ¥Äê9ÔÂ·Ý React ÍŶӷ¢²¼ÁË v16.0 °æ±¾¿ªÊ¼£¬µ½18Äê3Ô¸շ¢²¼µÄ v16.3 °æ±¾£¬React
Â½ÐøÍÆ³öÁ˶àÏîÖØ°õÐÂÌØÐÔ£¬²¢¸Ä½øÁËÔÓй¦ÄÜÖз´À¡ºôÉùºÜ¸ßµÄһЩÎÊÌ⣬ÀýÈç render ·½·¨ÄÚµ¥½Úµã²ã¼¶Ç¶Ì×ÎÊÌ⣬ÌṩÉúÃüÖÜÆÚ´íÎó²¶×½£¬×é¼þÖ¸¶¨
render µ½ÈÎÒâ DOM ½Úµã (Portal) µÈÄÜÁ¦£¬ÒÔ¼°×îÐ嵀 Context API ºÍ
Ref API¡£ÎÒÃÇÔÚ¶ÔÒÔÉÏÐÂÌØÐÔ¾¹ýÒ»¶Îʱ¼äµÄʹÓùýºó£¬Í¨¹ý±¾ÎĽøÐÐһЩϸ½Ú·ÖÏíºÍ×ܽᡣ
Ò»¡¢render ·½·¨ÓÅ»¯

ΪÁË·ûºÏ React µÄ component tree ºÍ diff ½á¹¹Éè¼Æ£¬ÔÚ×é¼þµÄ render()
·½·¨Öж¥²ã±ØÐë°ü¹üΪµ¥½Úµã£¬Òò´Ëʵ¼Ê×é¼þÉè¼ÆºÍʹÓÃÖÐ×ÜÊÇÐèҪעÒâǶÌ׺óµÄ²ã¼¶±äÉÕâÊÇ React
µÄÒ»¸ö¾³£±»ÈËÚ¸²¡µÄÎÊÌâ¡£±ÈÈçÒÔϵÄÄÚÈݽṹ¾Í±ØÐëÔÙǶÌ×Ò»¸ö div ʹÆä±äΪµ¥½Úµã½øÐзµ»Ø£º
render() {
return ( <div>
×¢£º <p>²úƷ˵Ã÷Ò»</p> <p>²úƷ˵Ã÷¶þ</p>
</div>
);
} |
ÏÖÔÚÔÚ¸üРv16 °æ±¾ºó£¬Õâ¸öÎÊÌâÓÐÁËеĸĽø£¬render ·½·¨¿ÉÒÔÖ§³Ö·µ»ØÊý×éÁË£º
render() {
return [ "×¢:", <p key="t-1">²úƷ˵Ã÷Ò»</h2>,
<p key="t-2">²úƷ˵Ã÷¶þ</h2>,
];
} |
ÕâÑùȷʵÉÙÁËÒ»²ã£¬µ«´ó¼ÒÓÖ¼ÌÐø·¢ÏÖ´úÂ뻹ÊDz»¹»¼ò½à¡£Ê×ÏÈ TEXT ½ÚµãÐèÒªÓÃÒýºÅ°üÆðÀ´£¬Æä´ÎÓÉÓÚÊÇÊý×飬ÿÌõÄÚÈݵ±È»»¹ÐèÒªÌí¼Ó¶ººÅ·Ö¸ô£¬ÁíÍâ
element ÉÏ»¹ÐèÒªÊÖ¶¯¼Ó key À´¸¨Öú diff¡£¸øÈ˸оõ¾ÍÊDz»ÏñÔÚд JSX ÁË¡£
ÓÚÊÇ React v16.2 ³ÃÈÈ´òÌú£¬ÌṩÁ˸üÖ±½ÓµÄ·½·¨£¬¾ÍÊÇ Fragment:
render() {
return ( <React.Fragment>
×¢£º <p>²úƷ˵Ã÷Ò»</p> <p>²úƷ˵Ã÷¶þ</p>
</React.Fragment>
);
} |
¿ÉÒÔ¿´µ½ÊÇÒ»¸öÕý³£µ¥½Úµãд·¨£¬Ö±½Ó°ü¹üÀïÃæµÄÄÚÈÝ¡£µ«ÊÇ Fragment ±¾Éí²¢²»»á²úÉúÕæÊµµÄ DOM
½Úµã£¬Òò´ËÒ²²»»áµ¼Ö²㼶ǶÌ×Ôö¼Ó¡£
ÁíÍâ Fragment »¹ÌṩÁËÐ嵀 JSX ¼òд·½Ê½ <></>£º
render() {
return ( <>
×¢£º <p>²úƷ˵Ã÷Ò»</p> <p>²úƷ˵Ã÷¶þ</p>
</>
);} |
¿´ÉÏÈ¥ÊÇ·ñÊæ·þ¶àÁË¡£²»¹ý×¢ÒâÈç¹ûÐèÒª¸ø Fragment Ìí¼Ó key prop£¬ÊDz»Ö§³ÖʹÓüòдµÄ£¨ÕâÒ²ÊÇ
Fragment Ψһ»áÓöµ½ÐèÒªÌí¼ÓpropsµÄÇé¿ö£©:
<dl>
{props.items.map(item => (
// Òª´«keyÓò»ÁË <></> <Fragment
key={item.id}> <dt>{item.term}</dt>
<dd>{item.description}</dd> </Fragment>
))}
</dl> |
¶þ¡¢´íÎó±ß½ç (Error Boundaries)

´íÎó±ß½çÊÇÖ¸ÒÔÔÚ×é¼þÉ϶¨Òå componentDidCatch ·½·¨µÄ·½Ê½À´´´½¨Ò»¸öÓдíÎó²¶×½¹¦ÄܵÄ×é¼þ£¬ÔÚÆäÄÚǶÌ×µÄ×é¼þÔÚÉúÃü¹ý³ÌÖз¢ÉúµÄ´íÎ󶼻ᱻÆä²¶×½µ½£¬¶ø²»»áÉÏÉýµ½Íⲿµ¼ÖÂÕû¸öÒ³ÃæºÍ×é¼þÊ÷Òì³£
crash¡£
ÀýÈçÏÂÃæµÄÀý×Ó¾ÍÊÇͨ¹ýÒ»¸ö ErrorBoundary ×é¼þ¶ÔÆäÄÚµÄÄÚÈݽøÐб£»¤ºÍ´íÎó²¶×½£¬²¢ÔÚ·¢Éú´íÎóʱ½øÐжµµ×µÄUIչʾ£º
class ErrorBoundary
extends Component {
constructor(props) {
super(props);
this.state = { error: null };
}
componentDidCatch(error,
{componentStack}
) {
this.setState({
error,
componentStack,
});
}
render() {
if (this.state.error) {
return ( <> <h1>±¨´íÁË.</h1>
<ErrorPanel {...this.state} /> </>
);
}
return this.props.children;
}
}
export default function App(){
return (
<ErrorBoundary>
<Content />
</ErrorBoundary>
);
} |
ÐèҪעÒâµÄÊÇ´íÎó±ß½çÖ»Äܲ¶×½ÉúÃüÖÜÆÚÖеĴíÎó (willMount / render µÈ·½·¨ÄÚ)¡£ÎÞ·¨²¶×½Òì²½µÄ¡¢Ê¼þ»Øµ÷ÖеĴíÎó£¬Òª²¶×½ºÍ¸²¸ÇËùÓг¡¾°ÒÀÈ»ÐèÒªÅäºÏ
window.onerror¡¢Promise.catch¡¢ try/catch µÈ·½Ê½¡£
Èý¡¢React.createPortal()

Õâ¸ö API ÊÇÓÃÀ´½«²¿·ÖÄÚÈÝ·ÖÀëʽµØ render µ½Ö¸¶¨µÄ DOM ½ÚµãÉÏ¡£²»Í¬ÓÚʹÓà ReactDom.render
д´½¨Ò»¸ö DOM tree µÄ·½Ê½£¬¶ÔÓÚҪͨ¹ý createPortal() ¡°·ÖÀ롱³öÈ¥µÄÄÚÈÝ£¬Æä¼äµÄÊý¾Ý´«µÝ£¬ÉúÃüÖÜÆÚ£¬ÉõÖÁʼþðÅÝ£¬ÒÀÈ»´æÔÚÓÚÔ±¾µÄ³éÏó×é¼þÊ÷½á¹¹µ±ÖС£
class Creater
extends Component {
render(){
return ( <div onClick={() =>
alert("clicked!")
}> <Portal> <img src={myImg}
/> </Portal> </div>
);
}
}
class Portal extends Component {
render(){
const node = getDOMNode();
return createPortal(
this.props.children,
node
);
}
} |
ÀýÈçÒÔÉÏ´úÂ룬<Creater> ͨ¹ý <Portal> °ÑÀïÃæµÄ <img
> ÄÚÈÝäÖȾµ½ÁËÒ»¸ö¶ÀÁ¢µÄ½ÚµãÉÏ¡£ÔÚʵ¼ÊµÄ DOM ½á¹¹ÖУ¬img ÒѾÍÑÀëÁË Creater
±¾ÉíµÄ DOM Ê÷´æÔÚÓÚÁíÒ»¸ö¶ÀÁ¢½Úµã¡£µ«µ±µã»÷ img ʱ£¬ÈÔÈ»¿ÉÒÔÉñÆæµÄ´¥·¢µ½ Creater
ÄÚµÄ div É쵀 onclick ʼþ¡£ÕâÀïʵ¼ÊÒÀÀµÓÚ React ´úÀíºÍÖØÐ´ÁËÕûÌ×ʼþϵͳ£¬ÈÃÕû¸ö³éÏó×é¼þÊ÷µÄÂß¼µÃÒÔ±£³Öͬ²½¡£
ËÄ¡¢Context API

ÒÔǰµÄ°æ±¾ÖÐ Context API ÊÇ×÷Ϊδ¹«¿ªµÄʵÑéÐÔ¹¦ÄÜ´æÔڵģ¬Ëæ×ÅÔ½À´Ô½¶àµÄÉùÒôÒªÇó¶ÔÆä½øÐÐÍêÉÆ£¬ÔÚ
v16.3 °æ±¾£¬React ÍŶÓÖØÐÂÉè¼Æ²¢·¢²¼ÁËеĹٷ½ Context API¡£
ʹÓà Context API ¿ÉÒÔ¸ü·½±ãµÄÔÚ×é¼þÖд«µÝºÍ¹²ÏíijЩ "È«¾Ö" Êý¾Ý£¬ÕâÊÇΪÁ˽â¾öÒÔÍù×é¼þ¼ä¹²Ïí¹«¹²Êý¾ÝÐèҪͨ¹ý¶àÓàµÄ
props ½øÐвã²ã´«µÝµÄÎÊÌâ (props drilling)¡£±ÈÈçÒÔÏ´úÂ룺
const HeadTitle
= (props) => {
return ( <Text>
{props.lang.title} </Text>;
);
};
// Öмä×é¼þ
const Head = (props) => {
return (
<div>
<HeadTitle lang={props.lang} />
</div>
);
};
class App extends React.Component {
render() {
return (
<Head lang={this.props.lang} />;
);
}
}
export default App = connect((state) =>
{
return {
lang:state.lang
}
})(App); |
ÎÒÃÇΪÁËʹÓÃÒ»¸öÓïÑÔ°ü£¬°ÑÓïÑÔÅäÖô洢µ½Ò»¸ö store Àͨ¹ý Redux connect µ½¶¥²ã×é¼þ£¬È»¶ø½ö½öÊÇ×îµ×¶ËµÄ×Ó×é¼þ²ÅÐèÒªÓõ½¡£ÎÒÃÇÒ²²»¿ÉÄÜΪÿ¸ö×é¼þ¶¼µ¥¶À¼ÓÉÏ
connect£¬Õâ»áÔì³ÉÊý¾ÝÇý¶¯¸üеÄÖØ¸´ºÍ²»¿Éά»¤¡£Òò´ËÖмä×é¼þÐèÒªÒ»²ã²ã²»¶Ï´«µÝÏÂÈ¥£¬¾ÍÊÇËùνµÄ
props drilling¡£
¶ÔÓÚÕâÖÖÈ«¾Ö¡¢²»³£Ð޸ĵÄÊý¾Ý¹²Ïí£¬¾Í±È½ÏÊʺÏÓà Context API À´ÊµÏÖ£º
Ê×ÏȵÚÒ»²½£¬ÀàËÆ store£¬ÎÒÃÇ¿ÉÒÔÏÈ´´½¨Ò»¸ö Context£¬²¢¼ÓÈëĬÈÏÖµ£º
const LangContext
= React.createContext({
title:"ĬÈϱêÌâ"
}); |
È»ºóÔÚ¶¥²ãͨ¹ý Provider Ïò×é¼þÊ÷Ìṩ Context µÄ·ÃÎÊ¡£ÕâÀï¿ÉÒÔͨ¹ý´«Èë value
ÐÞ¸Ä Context ÖеÄÊý¾Ý£¬µ±value±ä»¯µÄʱºò£¬Éæ¼°µÄ Consumer ÄÚÕû¸öÄÚÈݽ«ÖØÐÂ
render£º
class App extends
React.Component {
render() {
return ( <LangContext.Provider
value={this.state.lang} > <Head
/> </LangContext.Provider>
);
}
} |
ÔÚÐèҪʹÓÃÊý¾ÝµÄµØ·½£¬Ö±½ÓÓà Context.Consumer °ü¹ü£¬ÀïÃæ¿ÉÒÔ´«ÈëÒ»¸ö render
º¯Êý£¬Ö´ÐÐʱ´ÓÖÐÈ¡µÃ Context µÄÊý¾Ý¡£
const HeadTitle
= (props) => {
return ( <LangContext.Consumer>
{lang => <Text>{lang.title}</Text>
} </LangContext.Consumer>
);
}; |
Ö®ºóµÄÖмä×é¼þÒ²²»ÔÙÐèÒª²ã²ã´«µÝÁË£¬ÉÙÁ˺ܶà props£¬¼õÉÙÁËÖмä©´«µ¼Ö³ö´í£¬´úÂëÒ²¸ü¼ÓÇåˬ£º
// Öмä×é¼þ
const Head = () => {
return ( <div> <HeadTitle />
</div>
);
}; |
ÄÇô¿´ÁËÉÏÃæµÄÀý×Ó£¬ÎÒÃÇÊÇ·ñ¿ÉÒÔÖ±½ÓʹÓà Context API À´´úÌæµôËùÓеÄÊý¾Ý´«µÝ£¬°üÀ¨È¥µô
redux ÕâЩÊý¾Ýͬ²½ library ÁË£¿Æäʵ²¢²»ºÏÊÊ¡£Ç°ÃæÒ²ÓÐÌáµ½£¬Context API Ó¦¸ÃÓÃÓÚÐèҪȫ¾Ö¹²ÏíÊý¾ÝµÄ³¡¾°£¬²¢ÇÒÊý¾Ý×îºÃÊDz»ÓÃÆµ·±¸ü¸ÄµÄ¡£ÒòΪ×÷ΪÉÏ²ã´æÔÚµÄ
Context£¬ÔÚÊý¾Ý±ä»¯Ê±£¬ÈÝÒ×µ¼ÖÂËùÓÐÉæ¼°µÄ Consumer ÖØÐ render¡£
±ÈÈçÏÂÃæÕâ¸öÀý×Ó£º
render() {
return ( <Provider value={{
title:"my title"
}} > <Content /> </Provider>
);
} |
ʵ¼Êÿ´Î render µÄʱºò£¬ÕâÀïµÄ value ¶¼ÊÇ´«ÈëÒ»¸öеĶÔÏó¡£Õ⽫ºÜÈÝÒ×µ¼ÖÂËùÓÐµÄ Consumer
¶¼ÖØÐÂÖ´ÐÐ render Ó°ÏìÐÔÄÜ¡£
Òò´Ë²»½¨ÒéÀÄÓà Context£¬¶ÔÓÚijЩ·ÇÈ«¾ÖµÄÒµÎñÊý¾Ý£¬Ò²²»½¨Òé×÷Ϊȫ¾Ö Context ·Åµ½¶¥²ãÖй²Ïí£¬ÒÔÃâµ¼Ö¹ý¶àµÄ
Context ǶÌ×ºÍÆµ·±ÖØÐÂäÖȾ¡£
Îå¡¢Ref API
³ýÁË Context API Í⣬v16.3 »¹ÍƳöÁËÁ½¸öÐ嵀 Ref API£¬ÓÃÀ´ÔÚ×é¼þÖиü·½±ãµÄ¹ÜÀíºÍʹÓÃ
ref¡£
ÔÚ´Ë֮ǰÏÈ¿´Ò»ÏÂÎÒÃÇ֮ǰʹÓà ref µÄÁ½ÖÖ·½·¨¡£
// stringÃüÃû»ñÈ¡
componentDidMount(){
console.log(this.refs.input);
}
render() {
return ( <input
ref="input"
/>
);
} |
// callback
»ñÈ¡
render() {
return ( <input
ref={el => {this.input = el;}}
/>
);
} |
ǰһÖÖ string µÄ·½Ê½±È½Ï¾ÖÏÞ£¬²»·½±ãÓÚ¶à×é¼þ¼äµÄ´«µÝ»ò¶¯Ì¬»ñÈ¡¡£ºóÒ»ÖÖ callback ·½·¨ÊÇ֮ǰ±È½ÏÍÆ¼öµÄ·½·¨¡£µ«ÊÇдÆðÀ´ÂÔÏÔÂé·³£¬¶øÇÒ
update ¹ý³ÌÖÐÓз¢ÉúÇå³ý¿ÉÄÜ»áÓжà´Îµ÷Óà (callback ÊÕµ½ null)¡£
ΪÁËÌáÉýÒ×ÓÃÐÔ£¬ÐÂ°æ±¾ÍÆ³öÁË CreateRef API À´´´½¨Ò»¸ö ref object, ´«µÝµ½
component µÄ ref ÉÏÖ®ºó¿ÉÒÔÖ±½Ó»ñµÃÒýÓãº
constructor(props)
{
super(props);
this.input = React.createRef();
}
componentDidMount() {
console.log(this.input);
}
render() {
return <input ref={this.input} />;
} |
ÁíÍ⻹ÌṩÁË ForwardRef API À´¸¨Öú¼ò»¯Ç¶Ì××é¼þ¡¢component ÖÁ element
¼äµÄ ref ´«µÝ£¬±ÜÃâ³öÏÖ this.ref.ref.ref µÄÎÊÌâ¡£
ÀýÈçÎÒÃÇÓÐÒ»¸ö°ü×°¹ýµÄ Button ×é¼þ£¬Ïë»ñÈ¡ÀïÃæÕæÕýµÄ button DOM element£¬±¾À´ÐèÒªÕâÑù×ö£º
class MyButton
extends Component {
constructor(props){
super(props);
this.buttonRef = React.createRef();
}
render(){
return ( <button ref={this.buttonRef}>
{props.children} </button>
);
}
}
class App extends Component {
constructor(props){
super(props);
this.myRef = React.createRef();
}
componentDidComponent{
// ͨ¹ýrefÒ»²ã²ã·ÃÎÊ
console.log(this.myRef.buttonRef);
}
render(){
return ( <MyButton ref={this.myRef}>
Press here </MyButton>
);
}
} |
ÕâÖÖ³¡¾°Ê¹Óà forwardRef API µÄ·½Ê½×öÒ»¸ö¡°´©Í¸¡±£¬¾ÍÄܼò±ãÐí¶à:
import { createRef,
forwardRef } from "react";
const MyButton = forwardRef((props, ref) =>
(
<button ref={ref}>
{props.children}
</button>
));
class App extends Component {
constructor(props){
super(props);
this.realButton = createRef();
}
componentDidComponent{
//Ö±½ÓÄõ½ inner element ref
console.log(this.realButton);
}
render(){
return (
<MyButton ref={this.realButton}>
Press here
</MyButton>
);
}
} |
×ܽá
ÒÔÉϾÍÊÇ React v16 ·¢²¼ÒÔÀ´¼¸¸ö±È½ÏÖØÒªºÍÓÐÓõÄÐÂÌØÐÔ£¬ÓÅ»¯µÄͬʱҲ´øÀ´ÁË¿ª·¢ÌåÑéµÄÌáÉý¡£ÁíÍâ
v16 ¶Ô±È֮ǰ°æ±¾»¹Óв»´íµÄ°ü´óС½µµÍ£¬Ò²ÊǷdz£¾ßÓÐÓÅÊÆµÄ£º

³ý´ËÖ®Í⣬ÏëÒªÁ˽â¸ü¶àµÄһЩ±ä¸ü±ÈÈçÉúÃüÖÜÆÚµÄ¸üР(getDerivedStateFromProps,
getSnapshotBeforeUpdate) ºÍ SSR µÄÓÅ»¯ (hydrate)£¬ÒÔ¼°¼´½«ÍƳöµÄ
React Fiber (async render) ¶¯Ïò£¬¿ÉÒÔµã»÷²é¿´ÔÎÄÁ˽â¸ü¶àµÄ¹Ù·½ÐÅÏ¢¡£
Õâô¶à¼¤¶¯ÈËÐĵÄÌØÐÔ£¬Èç¹ûÄ㻹ÔÚÓà v15 ÉõÖÁ¾É°æ£¬¾Í¸Ï¿ìÉý¼¶ÌåÑé°É£¡ |