Comment: Components (component) are the core of React, and understanding them helps build a good design structure.
What is a component (component)
Component runs you split the UI into separate, reusable parts. Like a JavaScript function, a component receives an input named props and returns a REACT element that describes what the user interface should look like. That's why React is called a declarative API, you just need to declare the UI you want, and then React take care of the specifics.
Component API
After installing React, you can use the API provided by React, which can be divided into 5 basic types.
- Render
- State
- Props
- Context
- Lifecycle Events
While a component can use all of the APIs, usually a component uses only a subset of the APIs, we can subdivide components that use different APIs into both stateful (stateful) and stateless (stateless) components.
- Stateful component usage (render,state and life cycle related events)
- Stateless component usage (Render,props and context)
This separates the data logic from the UI presentation layer, and the partitioning of responsibilities between components creates more reusable components that are especially important when building extensible applications.
Component mode
There are usually several components in the component pattern:
- Container
- presentational
- High-level components (higher order component "HOC ' s")
- Render Callback
Container
The container component (container component) is responsible for getting the data and then rendering the portion to the appropriate subassembly.
A container is your data or logic layer and leverages the stateful API to use lifecycle events you can connect state to redux or flux storage. In the Render method of the container component, you can use the presentational component to render a specific style.
Note: Because the container component needs to use the stateful API, the container component needs to be defined as a class and cannot be a pure function.
Let's define a component greeting, which has state, life cycle Componentdidmount events and render methods.
class Greeting extends React.Component {
constructor() {
super();
this.state = {
name: "",
};
}
componentDidMount() {
// AJAX
this.setState(() => {
return {
name: "William",
};
});
}
render() {
return (
<div>
<h1>Hello! {this.state.name}</h1>
</div>
);
}
}
Now let's improve Greeting and separate it into a container component and a presentational component.
Presentational
Presentational components use props, render, and context (stateless API's) , and since lifecycle-related apis are not needed, we can use pure functions to simplify the representation:
const GreetingCard = (props) => {
return (
<div>
<h1>Hello! {props.name}</h1>
</div>
)
}
Presentational components only get data and callback functions from props, which are provided by the container component.
The container component and the display component each encapsulate the data/logic and presentation parts into their respective components:
const GreetingCard = (props) => {
return (
<div>
<h1>{props.name}</h1>
</div>
)
}
class Greeting extends React.Component {
constructor() {
super();
this.state = {
name: "",
};
}
componentDidMount() {
// AJAX
this.setState(() => {
return {
name: "William",
};
});
}
render() {
return (
<div>
<GreetingCard name={this.state.name} />
</div>
);
}
}
Higher order components [HOC’s]
A high-level component is a function that takes a component as a parameter and then returns a new component.
This is a powerful mode, we can modify the input component's props (add, delete, change) and then return a new modified component, such as react-router-v4 withRouter () method can wrap any custom component, will The three-objects of the react-router history, location, and match are passed in, and no primary level is required. For example, Redux, you can use the connect({})() method to connect the display component to the data in the store.
Code demo:
import {withRouter} from 'react-router-dom';
class App extends React.Component {
constructor() {
super();
this.state = {path: ''}
}
componentDidMount() {
let pathName = this.props.location.pathname;
this.setState(() => {
return {
path: pathName,
}
})
}
render() {
return (
<div>
<h1>Hi! I'm being rendered at: {this.state.path}</h1>
</div>
)
}
}
export default withRouter(App);
When exporting a component, I encapsulate it with the withRouter() of react-router-v4. In the componentDidMount lifecycle, we use this.props.location.pathname to update our state. Since we use the withRouter high-level component, we can directly access this.props.locationlocation without directly using location as props directly. Incoming, very convenient.
Render callbacks
Similar to high-level components, render callbacks or render props can be used to reuse logic.
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
increment = () => {
this.setState(prevState => {
return {
count: prevState.count + 1,
};
});
};
render() {
return (
<div onClick={this.increment}>{this.props.children(this.state)}</div>
);
}
}
class App extends React.Component {
render() {
return (
<Counter>
{state => (
<div>
<h1>The count is: {state.count}</h1>
</div>
)}
</Counter>
);
}
}
In the Counter class, we embed this.props.childrn in render and take this.state as a parameter. Under the App class, we can wrap our components in the Counter component.
The essence of the Counter component is to expose the external attribute of the children. The child's specific rendering details are given to the Counter user. When using it, you only need to pass the component to the children of the Counter. Of course, other parameters can be used. If the children are not enough. . For example, to implement a chat list, each message has an avatar and a message content, and the specific avatar is a circle, and the specific message content is a text, which is given to an external user.