簡評:除了常見的 HOC 和 RenderProp 技巧,作者介紹了 7 個有用的知識點。
使用 Fragment 而不是 div
很多時候我們想要處理多個 component,但是 render 只允許返回一個 component,為了處理這個問題很可以使用 <div /> 標簽來包裝所有的 component 。但這會添加額外的 HTML 元素。所以官方的建議是推薦使用 React Fragments 來處理這個問題。
import React, { Fragment } from 'react';
function ListItem({ item }) {
return (
<Fragment>
<dt>{item.term}</dt>
<dd>{item.description}</dd>
</Fragment>
// 也可以使用 <>....</> 來替換 <Fragment>
// 等同于
// <>
// <dt>{item.term}</dt>
// <dd>{item.description}</dd>
// </>
);
}
function Glossary(props) {
return (
<dl>
{props.items.map(item => (
<ListItem item={item} key={item.id} />
))}
</dl>
);
}
context 用起來
Context 提供了一種方式將數(shù)據(jù)傳遞到整個 component 樹中,而不必手動為每一層 component 傳遞 props。
因此,如果你有多個需要值的 component,建議使用 context。如果只有一個子 component 需要使用這個值建議使用 compositions。
最少使用一個 Error Boundaries
React 16 附帶了一個驚艷的功能 Error Boundaries。使用 Error Boundaries 我們可以處理這種問題,子組件出現(xiàn)錯誤不會導(dǎo)致整個應(yīng)用報錯和白屏。
舉個例子: 定義一個 ErrorBoundary 組件
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, info) {
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
用法和其他組件一樣簡單:
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
注意:React15 中的 unstable_handleError 方法不再有效,需要替換成 componentDidCatch 方法。
在生產(chǎn)環(huán)境中使用 production build
官網(wǎng)提供了很多提高性能的 配置。只需要 10 分鐘即可給你的應(yīng)用帶來質(zhì)的飛躍,在部署到生產(chǎn)環(huán)境前別忘了檢查它們。
使用 Refs 來操縱元素
我們可以使用 Refs 來觸發(fā)動畫,文本選擇或焦點管理。
例如:
我們可以 獲取 inpout DOM 節(jié)點引用。
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
// Create a ref to store the textInput DOM element
this.textInput = React.createRef();
}
render() {
// Use the `ref` callback to store a reference to the text input DOM
// element in an instance field (for example, this.textInput).
return (
<input
type="text"
ref={this.textInput}
/>
);
}
}
然后就可以在合適的時機聚焦這個 <input />
focus() {
// Explicitly focus the text input using the raw DOM API
// Note: we're accessing "current" to get the DOM node
this.textInput.current.focus();
}
使用代碼拆分
如果你使用 create-react-app 創(chuàng)建應(yīng)用或使用 NextJs 會自動創(chuàng)建一個 webpack 配置文件,webpack 會將整個應(yīng)用打包到一個文件中,如果應(yīng)用程序變得復(fù)雜或者添加第三方庫都會導(dǎo)致最終生成的文件變大,導(dǎo)致應(yīng)用訪問速度變慢。這時候可以使用代碼拆分,創(chuàng)建多個輸出,在需要的時候才加載對應(yīng)的包,可以大大改善網(wǎng)頁加載時間。
可以使用 React.lazy 來實現(xiàn)代碼拆分。
使用方式也很簡單,這里簡單實現(xiàn)一個基于路由代碼分割的例子:
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import React, { Suspense, lazy } from 'react';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
</Switch>
</Suspense>
</Router>
);
注意: React.lazy 和 Suspense 暫不支持服務(wù)端渲染,如果服務(wù)端渲染想要實現(xiàn)這個功能可以使用 React Loadable。
靜態(tài)類型檢查
JavaScript 不會對類型進行檢查,這可能導(dǎo)致很多的問題??梢允褂妙愋蜋z查器(例如 Flow)來幫助我們提前發(fā)現(xiàn)錯誤。Flow 是有 facebook 開發(fā)的類型檢查器,可以給變量、函數(shù)和 React Component 添加而外的注釋是一個不錯的選擇。
原文鏈接:Concepts to become an advanced React developer
推薦閱讀:改進 GitHub 工作流的 15 個建議