Note:!!

React Basics (1)

React componentized development

11. Use the ES6 decorator syntax to simplify the use of advanced components

1. Download the plugin package: @babel/plugin-proposal-decorators

AddDecoratorsLegacy ()

const {addDecoratorsLegacy} = require('customize-cra');

module.exports = override( ... .// Add the decorator configuration
  	addDecoratorsLegacy()
);
Copy the code

3. Use:

@connect(null, {search})

2) Decorate withRouter advanced components: @withrouter

3) The nature of decorator syntax:

// The decorator syntax allows MyClass to have an a attribute
@demo
class MyClass {}function demo(target) {
  target.a = 1; } is equivalent to// Add an A attribute to MyClass
class MyClass {}function demo(target) {
  target.a = 1;
}
MyClass = demo(MyClass)
Copy the code

12. Component lifecycle (old) (Understand!)

1 – understand

1) Components go through specific phases from creation to death.

2) The React component contains a series of tick functions (lifecycle callbacks) that are called at specific times.

3) When we define a component, we do a specific job in a specific lifecycle callback function.

2- Component lifecycle (old)

1. Initialization phase: triggered by reactdom.render () — initial render

1) Constructor (): Creates the initialization method of the component object

2) componentWillMount(): The component is about to be loaded and rendered onto the page

3) Render (): This is where the component generates virtual DOM nodes

4) componentDidMount(): Components are actually used after being loaded

This hook does some initialization, such as starting a timer, sending a network request, subscribing to a message, and executing it only once.

2. Update phase: triggered by component internal this.setsate () or parent component render

1) componentWillReceiveProps () : called when will receive the component attributes

ShouldComponentUpdate (): when the component receives a new property or state (can return false, not update after receiving data, prevent render call redraw)

3) componentWillUpdate(): The component is about to update and cannot modify its properties and state

4) Render (): Component repaint => one that must be used

5) componentDidUpdate(): Component has been updated

3. The unloading components: by ReactDOM unmountComponentAtNode triggered ()

1) componentWillUnmount(): Component is about to be destroyed => Common

This is where you do some finishing touches, such as closing the timer, unsubscribing the message, and executing it only once.

Illustration:

Example:

Requirement: Define a summation component

Click the button to display the sum above +1

<div id="test"></div>
<script type="text/babel">
    // Create a component
    class Count extends React.Component{
        / / the constructor
        constructor(props){
            console.log('Count---constructor');
            super(props)
            // Initialization state
            this.state = {count:0}}// Add the 1 button callback
        add = () = >{
            // Get the original state
            const {count} = this.state
            // Update the status
            this.setState({count:count+1})}// Unload the callback of the component button
        death = () = >{
            ReactDOM.unmountComponentAtNode(document.getElementById('test'))}// Force the update button callback
        force = () = >{
            this.forceUpdate()
        }

        // The hook to be mounted by the component
        componentWillMount(){
            console.log('Count---componentWillMount');
        }

        // The component has mounted the hook
        componentDidMount(){
            console.log('Count---componentDidMount');
        }
    
        // The hook that the component will unload
        componentWillUnmount(){
            console.log('Count---componentWillUnmount');
        }
    
        // Control module updated "valve"
        shouldComponentUpdate(){
            console.log('Count---shouldComponentUpdate');
            return true
        }
    
        // The hook that the component will update
        componentWillUpdate(){
            console.log('Count---componentWillUpdate');
        }
    
        // The component's updated hook
        componentDidUpdate(){
            console.log('Count---componentDidUpdate');
        }
    
        render(){
            console.log('Count---render');
            const {count} = this.state;
            return(
                <div>
                    <h2>The current sum is: {count}</h2>
                    <button onClick={this.add}>I + 1 point</button>
                    <button onClick={this.death}>Uninstall the component</button>
                    <button onClick={this.force}>Force an update without changing any data in the state</button>
                </div>)}}// Test the parent component render
    // Parent component A
    class A extends React.Component{
        // Initialization state
        state = {carName:'Mercedes'}
    
        changeCar = () = >{
            this.setState({carName:'rolling'})}render(){
            return(
                <div>
                    <div>I'm component A</div>
                    <button onClick={this.changeCar}>To change</button>
                    <B carName={this.state.carName}/>
    			</div>)}}// Subcomponent B
    class B extends React.Component{
        // The component is going to receive the new props hook
        // This hook has a pit, the first time receiving props will not be called
        componentWillReceiveProps(props){
            console.log('B---componentWillReceiveProps',props);
        }
    
        // Control module updated "valve"
        shouldComponentUpdate(){
            console.log('B---shouldComponentUpdate');
            return true
        }
        // The hook that the component will update
        componentWillUpdate(){
            console.log('B---componentWillUpdate');
        }
    
        // The component's updated hook
        componentDidUpdate(){
            console.log('B---componentDidUpdate');
        }
    
        render(){
            console.log('B---render');
            return(
                <div>I am component B, and the vehicle I receive is :{this.props. CarName}</div>)}}// Render component
    ReactDOM.render(<Count/>.document.getElementById('test'))
    // ReactDOM.render(<A/>,document.getElementById('test'))
</script>
Copy the code

13. Component lifecycle (new) – after 16.4 (emphasis!)

1- Component lifecycle (new)

1. Initialization phase: triggered by reactdom.render () — initial render

​ 1) constructor()

​ 2) getDerivedStateFromProps()

​ 3) render()

ComponentDidMount () => componentDidMount() => componentDidMount() => componentDidMount();

3. Update phase: triggered by the rerender of this.setsate () inside the component or the parent component

​ 1) getDerivedStateFromProps()

​ 2) shouldComponentUpdate()

​ 3) render()

​ 4) getSnapshotBeforeUpdate()

​ 5) componentDidUpdate()

4. Unload components: by ReactDOM unmountComponentAtNode triggered ()

1) componentWillUnmount() => Usually uses this hook to do some loose ends, such as turning off the timer, unsubscriberingmessages, and executing only once.

2- The difference between old and new life cycles

1) new lifecycle abandoned three hooks (componentWillMount componentWillUpdate, componentWillReceiveProps),

If used now, there will be a warning, the next big version will need to be prefixed with UNSAFE_ to use, it may be completely deprecated, not recommended.

UNSAFE_componentWillMount(){
	console.log('---componentWillMount---')}UNSAFE_componentWillUpdate(){
	console.log('---componentWillUpdate---')}UNSAFE_componentWillReceiveProps(){
	console.log('---componentWillReceiveProps---')}Copy the code

2) Two new hooks getDerivedStateFromProps and getSnapshotBeforeUpdate are proposed

Illustration:

Example:

Requirement: Define a summation component

Click the button to display the sum above +1

<div id="test"></div>
<script type="text/babel">
	// Create a component
	class Count extends React.Component{
        / / the constructor
        constructor(props){
            console.log('Count---constructor');
            super(props)
            // Initialization state
            this.state = {count:0}}// Add the 1 button callback
        add = () = >{
            // Get the original state
            const {count} = this.state
            // Update the status
            this.setState({count:count+1})}// Unload the callback of the component button
        death = () = >{
            ReactDOM.unmountComponentAtNode(document.getElementById('test'))}// Force the update button callback
        force = () = >{
            this.forceUpdate()
        }
    		
        // If the value of state depends on props at any time, use getDerivedStateFromProps
        // This method is not called by an instance, it must be static
        // This method must return either a state object (identical to the state content) or NULL
        static getDerivedStateFromProps(props,state){
            console.log('getDerivedStateFromProps',props,state);
            return null;
            // Return the object of state obtained by props
            // return props;
        }
    
        // Take the snapshot before the update
        // This method must return snapshot value or NULL
        getSnapshotBeforeUpdate(){
            console.log('getSnapshotBeforeUpdate');
            return 'atguigu'
        }
    
        // The component has mounted the hook
        componentDidMount(){
            console.log('Count---componentDidMount');
        }
    
        // The hook that the component will unload
        componentWillUnmount(){
            console.log('Count---componentWillUnmount');
        }
    
        // Control module updated "valve"
        shouldComponentUpdate(){
            console.log('Count---shouldComponentUpdate');
            return true;
        }
    
        // The component's updated hook
        componentDidUpdate(preProps,preState,snapshotValue){
            console.log('Count---componentDidUpdate',preProps,preState,snapshotValue);
        }
    		
        render(){
            console.log('Count---render');
            const {count} = this.state
            return(
                <div>
                    <h2>The current sum is: {count}</h2>
                    <button onClick={this.add}>I + 1 point</button>
                    <button onClick={this.death}>Uninstall the component</button>
                    <button onClick={this.force}>Force an update without changing any data in the state</button>
                </div>)}}// Render component
    ReactDOM.render(<Count count={199} />.document.getElementById('test'));
</script>
Copy the code

Extension: Usage scenario of getSnapShotBeforeUpdate

  • What is the use of getSnapshotBeforeUpdate? ———— keep the DOM information from the original page until the page is actually updated

  • Note:

    1. This method must be used with componentDidUpdate.

    2. It only makes sense to return DOM related values.

    3. com ponentDidUpdate will receive three parameters: preProps, preState, snapshotValue

Example:

<div id="test"></div>
<script type="text/babel">
	class NewsList extends React.Component{
        state = {newsArr: []};componentDidMount(){
            setInterval(() = > {
                // Get the original state
                const {newsArr} = this.state;
                // Simulate a news item
                const news = 'news'+ (newsArr.length+1);
                // Update the status
                this.setState({newsArr:[news,...newsArr]});
            }, 1000);
        }
    
    	// Get snapshot before update
        getSnapshotBeforeUpdate(){
            return this.refs.list.scrollHeight;
        }

        componentDidUpdate(preProps,preState,height){
            this.refs.list.scrollTop += this.refs.list.scrollHeight - height;
            // this.refs.list.scrollTop += 30;
        }

        render(){
            return(
                <div className="list" ref="list">
                {
                    this.state.newsArr.map((n,index)=>{
                        return <div key={index} className="news">{n}</div>})}</div>
        	)
    	}
    }
    ReactDOM.render(<NewsList/>.document.getElementById('test'))
</script>
Copy the code

14. Virtual DOM, DOM Diff algorithm and key’s role (heavy and difficult!)

1) Virtual DOM in-depth

1. An Object of type Object (general Object), or rather a tree of objects (inverted).

2. Virtual DOM stores the hierarchical relationship and some basic properties of the real DOM, corresponding to the real DOM

3. If you just update the virtual DOM, the page will not be redrawn.

2). Basic steps of DOM Diff algorithm (emphasis!)

1. Use JS object tree to represent the structure of the DOM tree, and then use this tree to build a real DOM tree inserted into the document.

2. When the state changes, a new object tree is constructed. Then compare the new tree with the old tree and note the differences between the two trees.

3. Apply the difference to the real DOM tree and the view is updated.

3) Further understanding (key!)

  • The Virtual DOM is essentially a cache between JS and DOM.

  • The analogy is CPU and hard disk, since hard disk is so slow, we put a cache between them, and DOM is so slow, we put a cache between JS and DOM.

  • The CPU (JS) only operates on memory (the Virtual DOM) and writes changes to the hard disk (DOM) at the end.

Illustration:

4) Verify the existence of diff algorithm

<div id="test"></div>
<script type="text/babel">
	class Time extends React.Component {
		state = {date: new Date()}

        componentDidMount () {
            setInterval(() = > {
                this.setState({
                    date: new Date()})},1000)
        }
    
        render () {
            return (
                <div>
                    <h1>hello</h1>// Direct reuse, no update<input type="text"/>// Direct reuse, no update<span>Now is: {this. State. Date. ToTimeString ()} / / input here will not update, reuse directly, because the diff is the smallest size is the label<input type="text"/>
            		</span>
        		</div>
        	)
        }
    }
    
    ReactDOM.render(<Time/>.document.getElementById('test'))
</script>
Copy the code

5) React key

1). React /vue key (What’s the inner workings of Key?)

2). Why is it best not to use index for key when iterating through a list?

Answer:

1. Functions of key in the virtual DOM:

1). To put it simply: The key is the identity of the virtual DOM object and plays an extremely important role in updating the display.

React generates a new virtual DOM when the data in the state changes.

React then makes a diff comparison between [new virtual DOM] and [old virtual DOM]. The comparison rules are as follows:

A. The same key as the new virtual DOM is found in the old virtual DOM:

(1). If the content in the virtual DOM remains unchanged, use the previous real DOM directly

(2). If the content in the virtual DOM changes, a new real DOM is generated and the previous real DOM in the page is replaced

B. The old virtual DOM does not have the same key as the new virtual DOM

Create a new real DOM from the data and render it to the page

2. Problems caused by using index as key:

1) If the data is added or deleted in reverse order, the sequence is broken:

Produces unnecessary real DOM updates to the ==> interface, which is fine, but inefficient.

If the structure also contains the DOM of the input class:

Error DOM update ==> interface problem.

3) pay attention! If there is no sequential operation such as adding or deleting data in reverse order,

For rendering lists only for presentation, using index as the key is fine.

3. How to select key in development?

1) It is better to use the unique identifier of each piece of data as the key, such as ID, mobile phone number, ID number, student number and other unique values.

2) If you are sure to simply display data, use index.

Extension: Key comparison process in diff

1. Use index as the key

Initial data:

{id:1,name:' xiao Zhang ',age:18}, {id:2,name:' Xiao Li ',age:19},Copy the code

The initial virtual DOM:

< li key = 0 > zhang - 18 < input type = "text" / > < / li > < li key = 1 > xiao li - 19 < input type = "text" / > < / li >Copy the code

Updated data:

{id: 3, name: 'wang' age: 20}, {id: 1, name: 'xiao zhang, age: 18}, {id: 2, name: xiao li, age: 19},Copy the code

Virtual DOM after data update:

< li key = 0 > wang - 20 < input type = "text" / > < / li > < li key = 1 > zhang - 18 < input type = "text" / > < / li > < li key = 2 > xiao li - 19 < input type="text"/></li>Copy the code

2. Use a unique ID as a key

Initial data:

{id:1,name:' xiao Zhang ',age:18}, {id:2,name:' Xiao Li ',age:19},Copy the code

The initial virtual DOM:

< li key = 0 > zhang - 18 < input type = "text" / > < / li > < li key = 1 > xiao li - 19 < input type = "text" / > < / li >Copy the code

Updated data:

{id: 3, name: 'wang' age: 20}, {id: 1, name: 'xiao zhang, age: 18}, {id: 2, name: xiao li, age: 19},Copy the code

Virtual DOM after data update:

< li key = 3 > wang - 20 < input type = "text" / > < / li > < li key = 1 > zhang - 18 < input type = "text" / > < / li > < li key = 2 > xiao li - 19 < input type="text"/></li>Copy the code

The instance

<div id="test"></div>
<script type="text/babel">
	class Person extends React.Component{

		state = {
			persons:[
				{id:1.name:'zhang'.age:18},
				{id:2.name:'xiao li'.age:19},
			]
		}
	
		add = () = >{
			const {persons} = this.state;
			const p = {id:persons.length+1.name:'wang'.age:20};
			this.setState({persons:[p,...persons]});
		}
	
		render(){
			return (
				<div>
					<h2>Display personnel information</h2>
					<button onClick={this.add}>Add a little wang</button>
					<h3>Use index as the key</h3>
					<ul>
						{
							this.state.persons.map((personObj,index)=>{
								return <li key={index}>{personObj.name}---{personObj.age}<input type="text"/></li>})}</ul>
					<hr/>
					<hr/>
					<h3>Use id (the unique identification of the data) as the key</h3>
					<ul>
						{
							this.state.persons.map((personObj)=>{
								return <li key={personObj.id}>{personObj.name}---{personObj.age}<input type="text"/></li>})}</ul>
				</div>
			)
		}
	}
	
	ReactDOM.render(<Person/>.document.getElementById('test'));
</script>
Copy the code

15. Use the React developer tool to debug

  • Install React Developer Tools for chrome App Store

  • The Browser debugger features the Components option in react web pages for developers to debug Components

16.React performance optimization

16.1 Component Optimization – Class components

1.Com Ponent 2 problems

1) As long as setState() is executed, the component will rerender () even without changing the state data => inefficient

  • Such as this. SetState ({})

2) When the current component is rerender (), the child component is automatically rerender, even if the child component does not use any data from the parent component => inefficient

Reason 2.

  • ShouldComponentUpdate () in Component always returns true

3. Efficient practices

  • Rerender () only if the component’s state or props data changes

4. Solve

Method 1: Override shouldComponentUpdate(nextProps, nextState)

  • Compare the old and new state or props data, returning true if there is a change, false if there is no change

2) Method 2: Inherit the class from PureComponent

  • PureComponent overrides shouldComponentUpdate() to return true only if the state or props data changes

  • This is a shallow comparison between the props and state data. If only the internal data of the data object has changed, return false

  • Instead of modifying state data directly, generate new data

Note:

  • Projects typically use PureComponent for optimization

The instance

import React, { PureComponent } from 'react'
import './index.css'

export default class Parent extends PureComponent {

	state = {carName:"Mercedes c36".stus: ['zhang'.'xiao li'.'wang']}

	addStu = () = >{
		This.setState({stus}) */ * const {stus} = this.state stus. Unshift (' r ') this.setstate ({stus}) */

		const {stus} = this.state
		this.setState({stus: ['liu'. stus]}) } changeCar =() = >{
		//this.setState({carName:' maybach '})

		const obj = this.state
		obj.carName = maybach
		console.log(obj === this.state);
		this.setState(obj)
	}

	/* shouldComponentUpdate(nextProps,nextState){ // console.log(this.props,this.state); // Current props and state // console.log(nextProps,nextState); // Props, target state return! this.state.carName === nextState.carName } */

	render() {
		console.log('Parent---render');
		const {carName} = this.state
		return (
			<div className="parent">
				<h3>I'm the Parent component</h3>
				{this.state.stus}&nbsp;
				<span>My carName is: {carName}</span><br/>
				<button onClick={this.changeCar}>Let me change</button>
				<button onClick={this.addStu}>Add a small liu</button>
				<Child carName="Rolling"/>
			</div>)}}class Child extends PureComponent {

	/* shouldComponentUpdate(nextProps,nextState){ console.log(this.props,this.state); // Current props and state console.log(nextProps,nextState); // Props, target state return! this.props.carName === nextProps.carName } */

	render() {
		console.log('Child---render');
		return (
			<div className="child">
				<h3>I am the Child component</h3>
				<span>The car I received was: {this.props. CarName}</span>
			</div>)}}Copy the code

16.2 Higher-order Components Memo – Functional component optimization

1. Memo () wraps the function component and returns an optimized new component

import React, { PureComponent, memo } from 'react';

// Header
const MemoHeader = memo(function Header() {
  console.log("Header is called.");
  return <h2>I'm a Header component</h2>
})

class Banner extends PureComponent {
  render() {
    console.log("Banner Render function called");
    return <h3>I am the Banner component</h3>}}const MemoProductList = memo(function ProductList() {
  console.log("ProductList called");
  return (
    <ul>
      <li>List of Goods 1</li>
      <li>Item List 2</li>
      <li>Item List 3</li>
      <li>Item List 4</li>
      <li>Item List 5</li>
    </ul>)})// Main
class Main extends PureComponent {
  render() {
    console.log("Main Render function called");
    return (
      <div>
        <Banner/>
        <MemoProductList/>
      </div>)}}// Footer
const MemoFooter = memo(function Footer() {
  console.log("Footer is called");
  return <h2>I'm Footer component</h2>
})

export default class App extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      counter: 0}}render() {
    console.log("App render function called");
    return (
      <div>
        <h2>Current count: {this.state.counter}</h2>
        <button onClick={e= > this.increment()}>+1</button>
        <MemoHeader/>
        <Main/>
        <MemoFooter/>
      </div>)}increment() {
    this.setState({
      counter: this.state.counter + 1}}})Copy the code

17.Fragment

1. Use

<Fragment><Fragment> Can only set key attributes or <></> cannot pass any attributesCopy the code

2. The role

  • You don’t have to have a real DOM root tag

Characteristics of 3.

  • This component is not loaded into the DOM

The instance

export default class Demo extends Component {
	render() {
		return (
			<Fragment key={1}>
				<input type="text"/>
				<input type="text"/>
			</Fragment>)}}Copy the code

18. The use of the Portals

  • In some cases, we want to render content independent of the parent component, or even independent of the DOM element currently mounted (by default, it is mounted to the DOM element with the ID root).
  • Portal provides an excellent solution for rendering child nodes to DOM nodes that exist outside the parent component:
    • ReactDOM.createPortal(child, container);
    • The first argument (child) is any renderable React child, such as an element, string, or fragment;
    • The second argument (container) is a DOM element;
  • In general, when you return an element from the render method of a component, the element will be mounted to its nearest parent in the DOM node:
  • However, sometimes it is beneficial to insert child elements at different locations in a DOM node.

Example:

1. Default

render() {
    return (
        //React mounts a new div and renders its child elements
        <div>
            {this.props.children}
        </div>
    );
}
Copy the code

2. The use of the Portals

render() {
    return ReactDOM.createPortal(
        this.props.children,
        domNode
    );
}
Copy the code

Modal component case

  • Develop a Modal component that renders its children to the middle of the screen:
    • Step 1: Modify index.html to add a new node
    • Step 2: Style the node
    • Step 3: Write component code
//index.css
#modal {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

//index.html
<div id="root"></div>
<div id="modal"></div>

//app.js
import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom';
import "./css/index.css";

class Modal extends PureComponent {
  render() {
    return ReactDOM.createPortal(
      this.props.children,
      document.getElementById("modal"))}}class Home extends PureComponent {
  render() {
    return (
      <div>
        <h2>Home</h2>
        <Modal>
          <h2>Title</h2>
        </Modal>
      </div>)}}export default class App extends PureComponent {
  render() {
    return (
      <div>
        <Home/>
      </div>)}}Copy the code

19.StrictMode

  • StrictMode is a tool for highlighting potential problems in your application.
    • Like fragments, StrictMode does not render any visible UI;
    • It triggers additional checks and warnings for its descendant elements;
    • Strict mode checking runs only in development mode; They do not affect production builds;
  • Strict mode can be enabled for any part of the application:
    • No strict schema checking is run on Header and Footer components;
    • However, ComponentOne and ComponentTwo and all their descendants will be checked;
<Header />
<React.StrictMode>
    <div>
    	<ComponentOne />
        <ComponentTwo />
    </div>
</React.StrictMode>
<Footer />
Copy the code
  • What does strict mode check for?

    • 1. Identify unsafe lifecycles

    • 2. Use the outdated REF API

    • 3. Use the obsolete findDOMNode method

      • In the React API, you could get the DOM from findDOMNode, but this is no longer recommended
    • 4. Check for unexpected side effects

      • The component’s constructor is called twice;

      • This is intentional in strict mode, to let you see if some of the logic written here has any side effects when called multiple times;

      • In a production environment, it is not called twice;

    • 5. Detect stale context apis

      • Context is used by declaring the properties of the Context object through the static property, returning the Context object through getChildContext, etc.

      • This method is no longer recommended

React style

1. Componentized CSS

  • The whole front end is already componentized:

    • CSS is not designed for componentization, so in the current componentization framework is in need of a suitable CSS solution.
  • Selecting the right CSS solution in componentization should meet the following criteria:

    • You can write local CSS: CSS has its own scope and does not contaminate the native components in other components.
    • You can write dynamic CSS: you can get some state of the current component and generate different CSS styles according to the state changes;
    • Support all CSS features: pseudo class, animation, media query, etc.
    • Write simple and convenient, preferably consistent CSS style features;
    • .

2. The React of CSS

  • In fact, CSS has always been a pain point in React, which has been teased and criticized by many developers.

  • Vue does this better than React:

    • Vue writes its own styles by writing a < style >< /style > tag in a.vue file;

    • To determine whether a written style is globally or locally valid, add the scoped attribute.

    • Use the lang attribute to set your favorite less, sass and other preprocessors.

    • Use inline style styles to set and change CSS according to the latest state.

    • .

  • Vue is not perfect in CSS, but it is simple, natural and convenient. At least the unified style will not be used by multiple developers or projects.

  • React, by contrast, does not officially provide a unified style for React:

    • From ordinary CSS, to CSS Modules, to CSS in JS, there are dozens of different solutions, hundreds of different libraries;

    • Everyone is looking for the best or most suitable CSS solution, but so far there is no unified solution;

3. Inline style

  • Inline styles are the official recommended way to write CSS styles:

    • Style takes a JavaScript object with a small camel name attribute, not a CSS string;

    • And you can reference the state in state to set the associated style;

  • Advantages of inline style:

    • 1. Inline styles, no conflict between styles

    • 2. You can dynamically obtain the current state

  • Disadvantages of inline style:

    • 1. All writing methods need to use the hump logo

    • 2. Some styles don’t have prompts

    • 3. Lots of styles and confusing code

    • 4. Some styles cannot be written (such as pseudo-classes/pseudo-elements)

  • So the official hope is still inline appropriate and normal CSS written in combination;

import React, { PureComponent } from 'react'

export default class App extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      color: "purple"}}render() {
    const pStyle = {
      color: this.state.color,
      textDecoration: "underline"
    }

    return (
      <div>
        <h2 style={{fontSize: "50px", color: "red}} ">I am heading</h2>
        <p style={pStyle}>I'm a text description</p>
      </div>)}}Copy the code

4. Common CSS

  • Normal CSS is usually written in a separate file and introduced later.

  • This is written in the same way as in normal web development:

    • If we follow the common web standards to write, then there won’t be too much of a problem;

    • However, in componentized development, we always want components to be independent modules, and even the styles are only valid within themselves, and do not affect each other.

    • But common CSS are global CSS, and styles affect each other;

  • The biggest problem with this approach is that styles overlap with each other;

// Profile/style.css
.profile .title {
  color: yellow;
}

// Profile/index.js
import React, { PureComponent } from 'react';
import './style.css';

export default class Profile extends PureComponent {
  render() {
    return (
      <div className="profile">
          <h2 className="title">I'm the title of the Profile</h2>
          <ul className="settings">
            <li>Setting Listing 1</li>
            <li>Settings Listing 2</li>
            <li>Setting Listing 3</li>
          </ul>
      </div>)}}// Home/style.css
.home .title {
  font-size: 30px;
  color: red;
}

.home .banner {
  color: orange;
}

// Home/index.js
import React, { PureComponent } from 'react';
import './style.css';

export default class Home extends PureComponent {
  render() {
    return (
      <div className="home">
        <h2 className="title">I'm the title of home</h2>
        <div className="banner">
          <span>Shuffling figure</span>
        </div>
      </div>)}}// App/style.css
#app > .title {
  color: blue;
}

// App/index.js
import React, { PureComponent } from 'react';
import './style.css';

import Home from '.. /home';
import Profile from '.. /profile';

export default class App extends PureComponent {
  render() {
    return (
      <div id="app">
        App
        <h2 className="title">I'm the title of the App</h2>
        <Home/>
        <Profile/>
      </div>)}}Copy the code

5.css modules

  • CSS modules are not a React specific solution, but can be used in any environment that uses a webPack-like configuration.

    • However, if it is used in other projects, we need to configure it ourselves, such as modules: True in webpack.config.js.
  • The React scaffolding has CSS modules built into it:

    • . CSS /. Less /. SCSS etc. Style files are modified into the module. The CSS /. The module. The less /. The module. The SCSS, etc.;

    • Then it can be referenced and used;

  • CSS modules do solve the problem of local scope, and it’s a solution that many people like to use in React.

  • But this approach has its drawbacks:

    • The name of the referenced class, which cannot use the hyphen (.home-title), is unreadable in JavaScript;

    • All classnames must be written in the {style.className} form;

    • It is not convenient to change some styles dynamically, so you still need to use inline styles.

  • If you’re OK with the above flaws, you can always use CSS Modules for your development, and it’s a popular way to write React.

// Profile/style.module.css
.title {
  color: yellow;
}

.setting {

}

.settingItem {

}

// Profile/index.js
import React, { PureComponent } from 'react';
import style from './style.module.css';

export default class Profile extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      color: "purple"}}render() {
    return (
      <div className="profile">
        <h2 className={style.title} style={{color: this.state.color}} >I'm the title of the Profile</h2>
        <ul className={style.settings}>
          <li className={style.settingItem}>Setting Listing 1</li>
          <li>Settings Listing 2</li>
          <li>Setting Listing 3</li>
        </ul>
      </div>)}}// Home/.module.css
.title {
  font-size: 30px;
  color: red;
}

.banner {
  color: orange;
}

// Home/index.js
import React, { PureComponent } from 'react';
import homeStyle from './style.module.css';

export default class Home extends PureComponent {
  render() {
    return (
      <div className="home">
        <h2 className={homeStyle.title}>I'm the title of home</h2>
        <div className={homeStyle.banner}>
          <span>Shuffling figure</span>
        </div>
      </div>)}}// App/.module.css
.title {
  color: blue;
}

// App/index.js
import React, { PureComponent } from 'react';
import appStyle from './style.module.css';

import Home from '.. /home';
import Profile from '.. /profile';

export default class App extends PureComponent {
  render() {
    return (
      <div id="app">
        App
        <h2 className={appStyle.title}>I'm the title of the App</h2>
        <Home/>
        <Profile/>
      </div>)}}Copy the code

6. Know CSS in JS (recommended!)

  • In fact, CSS in JS is mentioned in the official documentation:

    • “Css-in-js” refers to a pattern in which CSS is generated by JavaScript rather than defined in external files;

    • Note that this functionality is not part of React, but is provided by third-party libraries. React is not clear about how styles should be defined;

  • In traditional front-end development, we often separate structure (HTML), style (CSS), and logic (JavaScript).

    • However, as we mentioned in the previous study, React thought that logic and UI were inseparable, hence the syntax of JSX.

    • Style? Styles are also part of the UI;

    • In fact, csS-in-JS mode is a way to write style (CSS) into JavaScript, and can easily use JavaScript state;

    • React is called All in JS;

  • Of course, this approach to development has its critics:

    • Stop using CSS in JavaScript for web development

    • Hackernoon.com/stop-using-…

Styled components (recommended!)

  • Despite the criticism, many of the best CSS-in-JS libraries are still powerful and convenient in our view:

    • Css-in-js endows CSS with some capabilities through JavaScript, including style nesting similar to CSS preprocessor, function definition, logic reuse, dynamic state modification, etc.

    • CSS preprocessors still have some capabilities, but getting dynamic state is still a tricky point;

    • Therefore, CSS-in-JS is currently the most popular solution for writing CSS with React;

  • What are the most popular csS-in-JS libraries?

    • styled-components

    • emotion

    • glamorous

  • Styled components is still the most popular CSS-IN-JS library in the community, so we will take the Style – Components as the main explanation.

  • Install styled – components:

    • yarn add styled-components

8. Styled – Components Principle – ES6 Label template string

  • ES6 has added the syntax for template strings, which many people can use.

  • But there is another way Template strings can be used: Tagged Template Literals.

  • A normal JavaScript function:

  • Normally, we call a function by its name (), but there is another way to call a function:

// 1. Basic use of template strings
const name = "why";
const age = 18;
const message = `my name is ${name}`;

// 2. Tag template string: a function can be called as a template string
function test(. args) {
    console.log(args);
}

// test("aaa", "ccc");

// test`aaaa`;
test`my name is ${name}, age is ${age}`;

test` font-size: 15px; color: red; `
Copy the code
  • If we insert another variable at call time:

    • The template string was split;

    • The first element is an array, which is a combination of strings split by module strings.

    • The following elements are passed in as module strings;

  • In the Styled Component, this is how the module string is parsed, resulting in the style we want

9. Styled basic use

  • Styled components Essentially creates a component through function calls:

    • This component is automatically added to a non-repeating class;

    • Styled – Components will add the style associated to the class;

  • In addition, it supports sample nesting similar to CSS preprocessors:

    • Support direct descendant selectors or descendant selectors, and write styles directly;

    • You can get the current element with the ampersand;

    • Direct pseudo-class selectors, pseudo-elements, etc.;

10. Props and attrs properties

1. Props can be penetrated

<HYInput type="password" color={this.state.color}/>
Copy the code

2. Props can be passed to the Styled component

  • To get props, pass an interpolation function to props as an argument to ${}.

  • This approach can effectively solve the problem of dynamic style;

3. Add the attrs attribute

const HYInput = styled.input.attrs({
  placeholder: "coderwhy".bColor: "red"
})`
  background-color: lightblue;
  border-color: ${props => props.bColor};
  color: ${props => props.color};
`
Copy the code

11. Styled Advanced features

1. Support style inheritance

2. Styled setting the theme

Styled – Components 12. Styled – Components

// Profile/index.js
import React, { PureComponent } from 'react';
import styled from 'styled-components';

/** * features: * 1. Props * 2. Attrs * 3. Pass state as the props property */

/ / 2. The use of attrs
const HYInput = styled.input.attrs({
  placeholder: "coderwhy".bColor: "red"
})`
  background-color: lightblue;
  border-color: ${props => props.bColor};
  color: ${props => props.color};
`

export default class Profile extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      color: "purple"}}render() {
    return (
      <div>
        <input type="password"/>{/* 1. Props pass state as the props attribute */}<HYInput type="password" color={this.state.color}/>
        <h2>I'm the title of the Profile</h2>
        <ul>
          <li>Setting Listing 1</li>
          <li>Settings Listing 2</li>
          <li>Setting Listing 3</li>
        </ul>
      </div>)}}// Home/style.js
import styled from 'styled-components';

export const HomeWrapper = styled.div` font-size: 12px; color: red; .banner { background-color: blue; span { color: #fff; &.active { color: red; } &:hover { color: green; } &::after { content: "aaa" } } /* .active { color: #f00; `} * /}

export const TitleWrapper = styled.h2`
  text-decoration: underline;
  color: ${props => props.theme.themeColor};
  font-size: ${props => props.theme.fontSize};
`


// Home/index.js
import React, { PureComponent } from 'react';

import { 
  HomeWrapper,
  TitleWrapper
} from "./style";

export default class Home extends PureComponent {
  render() {
    return (
      <HomeWrapper>
        <TitleWrapper>I'm the title of home</TitleWrapper>
        <div className="banner">
          <span>By figure 1</span>
          <span className="active">Shuffling in figure 2</span>
          <span>Shuffling in figure 3</span>
          <span>Shuffling in figure 4</span>
        </div>
      </HomeWrapper>)}}// App/index.js
import React, { PureComponent } from 'react';
import Home from '.. /home';
import Profile from '.. /profile';
import styled, { ThemeProvider } from 'styled-components';

const HYButton = styled.button` padding: 10px 20px; border-color: red; color: red; `

// const HYPrimaryButton = styled.button`
// padding: 10px 20px;
// border-color: red;
// color: #fff;
// background-color: green;
/ / `

// Style inheritance
const HYPrimaryButton = styled(HYButton)` color: #fff; background-color: green; `

export default class App extends PureComponent {
  render() {
    return (
      // Styled sets the theme
      <ThemeProvider theme={{themeColor: "red", fontSize: "30px}} ">
        <Home />
        <hr />
        <Profile />
        <HYButton>I'm a normal button</HYButton>
        <HYPrimaryButton>I'm the main button</HYPrimaryButton>
      </ThemeProvider>)}}Copy the code

13. Add classes to React

React JSX gives us plenty of flexibility as developers. You can use some logic to decide whether or not to add classes, just as you would with JavaScript code:

  • Add class methods to native React
{/* Add the class method */ to React}
<h2 className={"foo bar active title"}> I am the title1</h2>
<h2 className={"title"+ (isActive ? " active":"")} >I'm heading 2</h2>
<h2 className={["title", (isActive ? "active": "")].join(" ")} >I'm heading 3</h2>
Copy the code

2. Use a third-party library, classNames, to simplify writing

  • Similar to adding class methods in VUE
const {isActive} = this.state;
const isBar = false;
const errClass = "error";
const warnClass = 10;

{/* Add class */ to the classnames library}
<h2 className="foo bar active title""> < p style =" max-width: 100%; clear: both4</h2>
<h2 className={classNames("foo","bar","active","title")} >I'm heading 5</h2>
<h2 className={classNames({"active": isActive,"bar": isBar},"title")} >I'm heading 6</h2>
<h2 className={classNames("foo", errClass.warnClass{"active": isActive})} >I'm heading 7</h2>
<h2 className={classNames(["active","title"])} >I'm heading 8</h2>
<h2 className={classNames(["active","title"{"bar": isBar}])}>I'm heading 9</h2>
Copy the code