# Higher order component 與 Recompose

## Higher order component

> 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.

<https://reactjs.org/docs/higher-order-components.html>

可想像是我們有一個共用的邏輯要在許多component中共用，我們可以把邏輯寫在一個component中，然後使用例如：

```javascript
<WrappedComponent
  injectedProp={injectedProp}
  {...passThroughProps}
/>
```

如此將component包在HOC中，共用邏輯。

> ```
> 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.
> ```

## Recompose

<https://github.com/acdlite/recompose>

> Recompose is a React utility belt for function components and higher-order components. Think of it like lodash for React.
>
> 在Function component 與 higher-order components 不能使用例如setState等方法，所以可以用recompose之API來加上。
>
> 例如：加上一個counter state，然後用setCounter方法改變state
>
> ```javascript
> const enhance = withState('counter', 'setCounter', 0)
> const Counter = enhance(({ counter, setCounter }) =>
>   <div>
>     Count: {counter}
>     <button onClick={() => setCounter(n => n + 1)}>Increment</button>
>     <button onClick={() => setCounter(n => n - 1)}>Decrement</button>
>   </div>
> )
> ```

最後組成component時可寫為如下：

```javascript
const BookingFormWithProps = compose(
  setDisplayName('BookingForm'),
  withRouter,
  connect(mapStateToProps),
  withReload,
  withStateHandlers(localState(), localStateHandlers),
  Form.create({
    onValuesChange: executeSideEffects,
  }),
  withPreloadAndListener,
  mapProps(filterToBookingFormProps),
)(BookingForm);
```

**1.管理state可用withStateHandlers**

```javascript
const BookingFormWithProps = compose(....
withStateHandlers(localState(), localStateHandlers);
....)


localState寫上state的值
localStateHandler寫上改變state的function
```

**2.加上React 生命週期**

<https://github.com/acdlite/recompose/blob/master/docs/API.md#lifecycle>

使用`lifecycle({})`，之後可在裡面放入componentDidMount等方法。

```javascript
const PostsList = ({ posts }) => (
  <ul>{posts.map(p => <li>{p.title}</li>)}</ul>
)

const PostsListWithData = lifecycle({
  componentDidMount() {
    fetchPosts().then(posts => {
      this.setState({ posts });
    })
  }
})(PostsList);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://easonwang.gitbook.io/web_advance/react/higher-order-component-yu-recompose.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
