Foremost | Sharing about React, with an introduction to React component design patterns

1. Introduction to React

For front-end developers with certain experience, it is more helpful to understand the differences between it and other frameworks before learning React. React and Vue have many similarities. For example, they both use Virtual DOM to shield the native DOM API, both provide responsive components, and both advocate one-way data flow, but they are also very different:

First of all, React should not be called a framework, it should be called a library. React has clearly stated in its design philosophy that it generally refuses to add features that developers can implement; that is, rather than saying that React is a framework that includes all aspects of front-end research and development, It is better to simply regard it as a management engine for rendering functions, which only acts as the View layer in the MVC architectural pattern. This has also led to React paying more attention to how to achieve rendering more efficiently, rather than upper-level application solutions.

Therefore, without using React-based frameworks (Gatsby, Next.js, etc.), React itself lacks R&D standards (it can also be said that React is more open), which has caused many React beginners (including the author himself) to learn After finishing the basic grammar and API such as JSX and Hook, you will still be confused about which API to use and which React feature to use when solving problems encountered in actual projects.

Let's share a few very practical React component design patterns

2. React component design pattern

(1) HOC mode

Before understanding the HOC mode, you need to understand what is called: Cross-Cutting Concerns. Cross-cutting concerns can be simply understood as sharing the same functionality among multiple different components. These concerns usually represent the general requirements or secondary requirements of the system, such as permissions, logs, data conversion, etc.

The HOC mode is a mode that reuses the same processing logic in different scenarios. HOC is a JS function that accepts a component as a parameter, adds additional functions or data and returns a component.

The structure of the HOC is similar:

const higherOrderComponent = (DecoratedComponent) => () => {
  const extraProps = {
    // ...
  }
  return <DecoratedComponent {...extraProps} />
}

Many popular React frameworks use this pattern such as connect in Redux and withRouter in react-router.

(2) Display component and container component mode

This model believes that if components are divided into two types (presentation and container), it will be easier to manage and reuse components by separating concerns.

Usually we think that React components are composed of state, state operation function, and UI (JSX). If it is further subdivided, the state can be divided into visual state, interactive state and data state;

Then the so-called separation of concerns is to put JSX, visual state and visual operation functions into presentation components, and put interactive state, data state and their operation functions into container components;

Correspondingly, presentational components only need to accept parameters related to visibility, while parameters related to interaction and data are received by container components.

For example, a presentational component has a structure similar to:

const UsersList = ({ users }) => {
  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.username}</li>
      ))}
    </ul>
  )
}

The structure of the container component is similar:

const Users = ({ children }) => {
  const [state, setState] = useState({})
  useEffect(() => {
    fetchUsers()
  }, [])
  return React.cloneElement(children, { ...state })
}

Through the separation of concerns, in addition to the container component Users, other container components can also reuse UserList to display data. Similarly, UserList can also use other container components to provide data.

Note:
After React 16.8, using a Hook combination instead of a container component can usually reduce a lot of redundant code and make the code more concise; in the case of direct reuse of Hook, it is no longer necessary to develop a container component, but the data property The separation of state and interactivity state from presentational components is still valuable.

(3) Composite component mode

This pattern provides an efficient way for multiple components to share state and work together to accomplish a common goal.

For example: use Select component and Option component to implement drop-down selection, the structure is similar to:

const SelectContext = createContext()

const Select = ({ children }) => {
  const [activeOption, setActiveOption] = useState()
  return (
    <SelectContext.Provider value={
   
   { activeOption, setActiveOption }}>
      {children}
    </SelectContext.Provider>
  )
}

const Option = ({ key, children }) => {
  const { activeOption, setActiveOption } = useContext(SelectContext)
  if (!activeOption || !setActiveOption) {
    throw new Error('Option 组件不能单独使用')
  }
  return (
    <div
      className={activeOption === key ? 'active' : ''}
      onClick={() => setActiveOption(key)}
    >
      {children}
    </div>
  )
}

Select.Option = Option

export default Select

In this example, the Select and Option components share the activeOption state and its operating functions through the Context API, and the Option component is highly coupled with the Select component and cannot be used alone.

When using the composite component pattern, the corresponding client code can be more flexible, similar to:

export default function App() {
  return (
    <Select>
      <Select.Option key='oliver'>Oliver</Select.Option>
      <Select.Option key='eve'>Eve</Select.Option>
    </Select>
  )
}

There are several benefits to using the Composite Component pattern:

  1. Parent-child components can interact implicitly, without the need to pass in parameters from outside the component to control the interaction;

  2. The introduction of the Select component will automatically introduce the Option without manual introduction;

  3. Declarative UI components are more semantic.

The development experience of React is shared here. I hope this article can help you make full use of all the advantages of React to create scalable and maintainable React applications, and apply the right pattern in the right place to optimize your project.

Guess you like

Origin blog.csdn.net/CBGCampus/article/details/130082201