Open gracekrcx opened 4 years ago
用 withState 把 state 獨立出來,以下面的例子來說,counter 初始值是 0,setCounter 用來設定 counter 的值,counter 跟 setCounter 會被當成 props 傳進 Component 內
import { withState } from 'recompose'
const enhance = withState('counter', 'setCounter', 0)
const Counter = ({ counter, setCounter }) => (
<div>
Count: {counter}
<button onClick={() => setCounter(n => n + 1)}> + </button>
</div>
)
export default enhance(Counter)
import { compose } from 'recompose'
const MyComponent = () => (
// ...
)
const enhance = compose(hoc1, hoc2, hoc3)
export default enhance(MyComponent)
// export default hoc1(hoc2(hoc3(MyComponent))) // compose 由右到左
參考文章 對 recompose 的介紹
閱讀筆記 React Higher Order Components in depth
hocFactory:: W: React.Component => E: React.Component
W (Wrapped Component) is the React.Component being wrapped E (Enhanced Component) is the new, HOC, React.Component being returned.
被 wrap 的 component 可以 mean one of two things:
props proxy : HOC 對傳給 WrappedComponent 的 porps 進行操作 Inheritance Inversion : HOC 繼承 WrappedComponent
function iiHOC(WrappedComponent) {
return class Enhancer extends WrappedComponent { // 繼承 WrappedComponent
render() {
return super.render()
}
}
}
返回的 HOC 繼承(Enhancer)了 WrappedComponent。WrappedComponent 被動地被Enhancer 繼承,而不是WrappedComponent 去繼承 Enhancer。Inheritance Inversion 允許 HOC 通過 this 訪問到 WrappedComponent。(不是很懂就先記下來)
What can I do with HOCs?
看了些文章之後,覺得 state Abstraction 像是你如何對你取得的資料做一個資料結構上的配置,是 array 還是 object,要自己一個 key 還是和別人合在一起
參考文章: React 高階組件淺析 深入理解 React 高阶组件
接續上篇
使用參數在 HOCs 是很有用的 Example: HOC parameters with a trivial Props Proxy.
function HOCFactoryFactory(...params){
// do something with params
return function HOCFactory(WrappedComponent) {
return class HOC extends React.Component {
render() {
return <WrappedComponent {...this.props}/>
}
}
}
}
HOCFactoryFactory(params)(WrappedComponent)
Example: Parent Components accessing its children.
class Parent extends React.Component {
render() {
return (
<div>
{this.props.children}
</div>
)
}
}
}
render((
<Parent>
{children}
</Parent>
), mountNode)
Generally, if you can do it with Parent Components you should because it’s much less hacky than HOCs, but as the list above states they are less flexible than HOCs.
第一個 function call 的 output 是第二個 function call 的 input, As a result, we get a compound function.
const listGroup = items =>
listGroupTag(listGroupItems(items))
composed 之後
const listGroup = items =>
compose(listGroupTag, listGroupItems)(items)
好處: Breaking our code out into multiple library files allows us to reuse these functions in other projects.
文章: Functional JavaScript: Function Composition For Every Day Use
If you stick to this pattern, you’ll end up with reusable components that are both readable and easy to test as each component is only responsible for a single task.
Making components reusable means to decouple them from the data.
So, it’s all about functions. To be more precise, it’s all about simple functions. This means that each function should only be responsible for a single task. The simpler the function, the more reusable it is.
you also decorate the presentational component using HoC with the functionality you want. As a result, you can reuse a particular presentational component in different places of your application and decorate it with the HoC you want for a particular case.
By using the HoC pattern in the previous example, we moved all the logic to the HoC, and just let the base component render the UI. As a result, our presentational component became reusable since it just receives data as props and renders it to the screen.
The HoC and the base component are both reusable and independent of each other. The HoC doesn’t know where its data goes and the presentational component has no idea where its data is coming from.
This HoC doesn’t have any side effects. It doesn’t mutate anything. It’s a pure function.
If you need a complex logic for your presentational component, you don’t need to store it all inside a single component or in a single HoC. Instead, you just compose several simple HoCs together and enhance your presentational component with them.
The HoC pattern helps us to achieve this since its idea is to move the logic to the HoC and let the presentational functional component take care of the UI rendering.
最基本的 pattern
import React from 'react';
const higherOrderComponent = (WrappedComponent) => {
return class HOC extends React.Component {
render() {
return <WrappedComponent {...this.props} />;
}
}
};
The goal of this pattern is to decompose the logic into simpler and smaller functions that can be reused. A rule of thumb is a function does just one task and does it well. This also avoids side effects ( changing anything that is not owned by the function ) , and makes debugging and maintenance a whole lot easier.
Introduction to higher-order components (HOC) in React github
import _ from 'lodash';
import handleKeyboard from './handleKeyboard';
import restrictWebviewAccess from './restrictWebviewAccess';
import fillWidth from './fillWidth';
import sessionEvents from './sessionEvents';
import browserFunctionality from './browserFunctionality';
import reloadOnReactivate from './reloadOnReactivate';
import addSplash from './addSplash';
import WebView from './WebView'; // Base Component
// Compose the new webview
export default _.flow([
restrictWebviewAccess, // block access to external sites
browserFunctionality, // handle android back button
reloadOnReactivate, // reload after the app has been inactive
handleKeyboard, // make android not hide webview input
fillWidth,// make webview full width
sessionEvents, // add login, logout session events
addSplash // add splash to webview
])(WebView);
How then do we handle form specifics, props and state for multiple different forms?
Identify the state or props that every form should have
perhaps the following:
formAction
formName
handleChange
handleSubmit
inputNames
notes
errors
You can imagine that in a large app, this same pattern of subscribing to DataSource and calling setState will occur over and over again. We want an abstraction that allows us to define this logic in a single place and share it across many components. This is where higher-order components excel.
這段文裡出現了 abstraction, an abstraction 一個抽象,意思感覺是經過思考過後組合一個東西出來,所以 functional component 很常在翻譯的時候突然冒出一個直翻的抽象
由「為什麼 “abstraction”不應該譯為“抽象化”」談正名
「abstraction …中文應該像是萃取、或是提煉吧…。」 abstraction 是摘要/提取出你所需要或感興趣的系統物件或類別的特質。 「乘法是加法的抽象」
Function Parameters VS Arguments
higher-order component (HOC) in react
希望透過底下的問題去初步了解 HOC
官方文章 官方文件是一切的開頭。
A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React’s compositional nature. Concretely, a higher-order component is a function that takes a component and returns a new component.
翻譯: HOC 的目的是為了 reuse component 的 logic。 HOC 是一個 pattern,它們是從 React 的組成性質中產生的一種 pattern。
白話來說: HOC 是 react 用來 reuse component logic 的 pattern,讓元件透過 HOC 包裝後可以得到共同的功能,HOC 是一個 function,他輸入一個 component 然後回傳一個新的,或是說被附加功能的 component。
HOC 本質
是 Functional Programming 裡的 higher-order function higher-order function is a function that does at least one of the following:
HOC 不關心你傳遞的數據 (props) 是什麼,並且被包裝組件( WrappedComponent )不關心數據來源
HOC 實際應用
reuse component logic
react-redux 的 connect 上,或是官方的範例上可以清楚的了解,當有許多 component 需要在 componentDidMount 時做相同的事,這時就很適合用 HOC 這個 pattern
許多 component 都需要 loading 的控制或是 errorHandle, auth
// 1. 上面範例需要修改原來組件的代碼 // 2. 如果有其它組件,也需要 loading 功能,這時就需要重複寫相同的判斷邏輯
也可以用 pipe 函數,它和 compose 函數類似,pipe 的組合順序是從左到右而 compose 是『右到左』。
The compose utility function is provided by many third-party libraries including lodash (as lodash.flowRight), Redux, and Ramda.
註:component 是一個以資料為進、UI 為出的函數。link
結論
學習心得
接觸新東西,又是一個蠻大的主題時,很難由淺到深一次吸收,在有限的時間裡,先把該懂的基礎了解,艱深的範例之後有機會再回頭看
參考文章
High Order Component 如何理解React 高階組件(HOC)? 探索Vue高阶组件 進階 React Component Patterns 筆記(下) HOC 與Render Props,談我從她們身上學到什麼 React Developer 不可不知的 Higher Order Component(HOC / 高階元件) Understanding Higher-Order Components in React 從Redux來學習Functional Programming(compose篇) form example Higher Order Component(HOC) design pattern in React. Creating forms in React with hooks and HOC