preface
The React design idea embodies functional programming in many places. There are multiple ways to combine and reuse components. Here are some of the methods I use in daily development.
High order component
Aside from React, as a JavaScript developer, higher-order functions should have a lot of exposure, such as the common anti-shock and throttling (anti-shock and throttling). If we had to give it a definition, let’s look at the official, high-order component is a function that is passed in to the component and returned as a high-order component
In development, it is common to encounter the need to render the list as empty if the data is empty, if it is a single component need not matter, just add a judgment
render() { if (_.isEmpty(this.prop.dataSource)) { return <Empty />; }... }Copy the code
If there are multiple such judgments, the code repetition rate is high, and at this point we can consider using higher-order components to separate the empty judgments into a higher-order component
const withEmpty = (WrappedComponent) => {
return (props) => {
return _.isEmpty(props.dataSource)
? <Empty />
: <WrappedComponent {...props} />;
}
}
Copy the code
use
render() {
const WithEmptyUserList = withEmpty(UserList);
return <WithEmptyUserList dataSource={[]}/>;
}
Copy the code
There are many official instructions in the relevant section, please refer to advanced components
render prop
When calling a component, introduce a function prop that defines how the component should render, not necessarily called Render
const Mouse = ({ render }) => { const [x, setX] = useState(0); const handleMouseMove = (e) => { setX(e.pageX); } return <div onMouseMove={handleMouseMove}> {render({ x })} </div> } class App extends Component { constructor(props) { super(props) } render() { return ( <Mouse render={({ x }) => <p>{x}</p>} /> ) } }Copy the code
The Mouse component records the x coordinates of the movement, and the rendering is handed over to the Render function passed in by the parent component.
Child Component
This is common with react common components such as Context and react-router
// Context render() { return <Context.Consumer> {(props) => {... }} </Context.Consumer> }Copy the code
// React-router render() { return ( <HashRouter> <Route path='/' render={() => '/'} /> <Route path='/home' render={() => '/home'} /> </HashRouter> ) }Copy the code
There are many common components on the market with similar encapsulation, as well as several components such as ANTD
This implements an ultra-lazy version of the React-Router, hashRouter, and Route sections
const Context = createContext(); const HashRouter = ({ children }) => { const [match, setMatch] = useState(_.replace(location.hash, '#', '')); useEffect(() => { const handleHashChange = (value) => { setMatch(_.replace(location.hash, '#', '')); } window.addEventListener('hashchange', handleHashChange); return () => window.removeEventListener('hashchange', handleHashChange); } []); return <Context.Provider value={{ match }}> {children} </Context.Provider> } const Route = ({ path, render }) => { return <Context.Consumer> {({match}) => { if (match === path) { return render() }; return null; }} </Context.Consumer> } class App extends Component { constructor(props) { super(props) } render() { return ( <HashRouter> <Route path='/' render={() => '/'} /> <Route path='/home' render={() => '/home'} /> </HashRouter> ) } }Copy the code
The key step or two
HashRouter
Listen for route changes and preserve themhash
Value, render allchildren
Route
Compare the currenthash
And the incomingpath
, returns if correct
The real React-Router has a lot more judgment than this one. For example, it only performs the congruent operation on the hash value. In fact, the judgment of Route is much more complicated
{props.match
? children
? typeof children === "function"
? __DEV__
? evalChildrenDev(children, props, this.props.path)
: children(props)
: children
: component
? React.createElement(component, props)
: render
? render(props)
: null
: typeof children === "function"
? __DEV__
? evalChildrenDev(children, props, this.props.path)
: children(props)
: null}
Copy the code
Recommended to read the relevant source code
conclusion
A lot of the code in this article uses hook. All versions below 16.8 May have problems. The above summary is based on several reuse methods commonly used in my daily work, welcome to discuss
🏆 nuggets technical essay | double festival special articles