Features
Error Boundary
以下是错误边界不起作用的情况:
- 事件处理器内代码.
setTimeout或requestAnimationFrame回调中的异步代码.- 服务端渲染代码.
- 错误边界代码本身.
React Error Boundary library:
class ErrorBoundary extends React.Component<{ children: ReactElement }> {
state = {
hasError: false,
error: null,
info: null,
}
// key point
componentDidCatch(error, info) {
this.setState({
hasError: true,
error,
info,
})
}
render() {
if (this.state.hasError) {
return (
<div>
<h1>Oops, something went wrong :(</h1>
<p>
The error:
{this.state.error.toString()}
</p>
<p>
Where it occurred:
{this.state.info.componentStack}
</p>
</div>
)
}
return this.props.children
}
}
React Fragment
- Less node, less memory, faster performance.
- Avoid extra parent-child relationship for CSS flex and grid layout.
- DOM debug inspector is less cluttered.
class Items extends React.Component {
render() {
return (
<>
<Fruit />
<Beverages />
<Drinks />
</>
)
}
}
class Fruit extends React.Component {
render() {
return (
<>
<li>Apple</li>
<li>Orange</li>
<li>Blueberry</li>
<li>Cherry</li>
</>
)
}
}
class Frameworks extends React.Component {
render() {
return (
<>
<p>JavaScript:</p>
<li>React</li>
,
<li>Vuejs</li>
,
<li>Angular</li>
</>
)
}
}
React Portal
Portal provide a first-class way to render children into a DOM node
that exists outside the DOM hierarchy of the parent component
ReactDOM.createPortal(child, container).
<div id="root"></div>
<div id="portal"></div>
const portalRoot = document.getElementById('portal')
class Portal extends React.Component<{ children: ReactElement }> {
constructor() {
super()
this.el = document.createElement('div')
}
componentDidMount = () => {
portalRoot.appendChild(this.el)
}
componentWillUnmount = () => {
portalRoot.removeChild(this.el)
}
render() {
const { children } = this.props
return ReactDOM.createPortal(children, this.el)
}
}
interface Props {
on: boolean
toggle: Function
children: ReactElement
}
class Modal extends React.Component<Props> {
render() {
const { children, toggle, on } = this.props
return (
<Portal>
{on
? (
<div className="modal is-active">
<div className="modal-background" />
<div className="modal-content">
<div className="box">
<h2 className="subtitle">{children}</h2>
<button
type="button"
onClick={toggle}
className="closeButton button is-info"
>
Close
</button>
</div>
</div>
</div>
)
: null}
</Portal>
)
}
}
class App extends React.Component {
state = {
showModal: false,
}
toggleModal = () => {
this.setState({
showModal: !this.state.showModal,
})
}
render() {
const { showModal } = this.state
return (
<div className="box">
<h1 className="subtitle">Hello, I am the parent!</h1>
<button
type="button"
onClick={this.toggleModal}
className="button is-black"
>
Toggle Modal
</button>
<Modal on={showModal} toggle={this.toggleModal}>
{showModal ? <h1>Hello, I am the portal!</h1> : null}
</Modal>
</div>
)
}
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />)