In this paper, the feed

This article is mainly about CRA scaffolding installation, React syntax, component classification and component value transfer, etc. If you’re an experienced developer with React, feel free to point out any problems or areas that could be improved, and I’d appreciate it! This is the react website

This paper is mainly divided into:

  • React Project construction
  • The React of grammar
  • React Component introduction
  • The React component transmits values
  • A simple little example of componentization
  • The React-Router is not covered in this article

It may take you 10-20 minutes to read the full text, but if you are interested, you can click on the code together (using the editor: VSCODE, plug-ins: VS Code ES7 React/Redux/ react-native /JS snippets. This plugin allows you to quickly build component formats.

So let’s start the body

1. Create the React project using scaffolding

First Thing First, we use create-react-app (nodejs environment required) to create this project. After all, there are other ways to create projects and services.

create-react-app mycode
mycode


  • npm startIf the development server is enabled, the default port is 3000, which is automatically displayed after the startuplocalhost:3000The page
  • npm run buildCreate packaged static files for the production environment
  • npm testOpen the test, which I haven’t used before, and those who have can share the technical article in the comments
  • npm run ejectEject unpacks all the tools (configuration files and package.json dependencies) to the application’s path, and the process is irreversible

So let’s get started, CD mycode & NPM start.

2. Basic grammar

Two important files in the project

  • public/index.htmlReact builds SPA, so index.html is our home page, which you can also see in the file<div id="root"></div>Root is where the root component is rendered.
  • src/index.jsThis is our main JS file,

    Here is the expression:render(<App></App>, window.root)Indicate that we use a render methodrenderThat will beAppRender to therootNo matter what you have in your App, how many levels there are, how many components there are, how much logic there is, there’s only one entry point.

Everything in React starts here

We delete all files under scaffolding SRC, create a blank index.js, and start coding.

In index.js, we need to import the React library, import the React -dom, import the root component, and execute the render method of the root component:

  • import React from 'react'Note that React must begin with a capital letter
  • import {Component} from 'react', introducing component methods, using{Component}Introduction of deconstruction
  • import App from './App', introducing the root component App, which we will create in the next stepsrc/App.jsAs our root component, you can call your root component JS by whatever name you want, but I like to call it App
  • render(<App></App>, window.root)Render component to root container,renderReact is the core render method that we’ll be using all the time

Grammar is introduced

(1) introduction of JSX

As described in the previous section, we can learn the basic syntax of React by coding in index.js. React’s core language is JSX.

const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

ReactDOM.render(
  element,
  document.getElementById('root'));Copy the code

HTML tags we write in React will actually be rendered to the page as above, but as a very sweet syntax candy, we don’t need to write reactdom.render (), instead

let el = <h1>hello <span>world</span></h1>
render(el,window.root);
Copy the code

Use javascript + XML syntax to define an element and render it. In index.js, you can comment out the original render(
, window.root) and replace it with the above code, which can be seen in localhost:3000

(2) < > and {}

The JSX element /react element is marked with a < sign. If you see {, you will think it contains JS code

1) execute js in {}

  • State variable
let str = '<h1>world</h1>'
let el = (
  <div>
    <div>{str}</div>
  </div>
)
render(el,window.root);
Copy the code

The page looks like this

The STR variable is executed in {}, and the content in the middle of the div should be the string ‘< H1 >world
‘, not the tag h1

  • The cancellation

What if we want to write comments in our code? Is that so //, oh no, add {//}? Oh no, you can see it in the editor

{/*hello*/}

  • String parsing to HTML In the first small example we mentioned that ‘< H1 >world’ is rendered as string content, but what if you really want to display the H1 as a DOM? Here we use

    , that’s a long API, right? We’re going to put dangerouslySetInnerHTML~ dangerouslySetInnerHTML on the container

    Doing so risks being inserted into maliciously executed scripts.

  • Execute a method

function a() { 
  return <h3>hello function</h3>
}

let el = (
  <div>
    <div>{a()}</div>
  </div>
)
Copy the code

Page:

  • When adding a key to a loop, it is best not to use the index of the array. In order to identify each element of the loop for dom-diff purposes, we usually use the ID. Handle array returns as arr.map
letArr = [1, 2, 3]; //let el = (
  arr.map((item, key) => (
    <li key={key}>{item}</li>
  ))
)
Copy the code

  1. Several features of HTML attributes in JSX
  • Class →className This hump replaces the native HTML class, but class can still be used, and scaffolding will prompt you to use className instead

  • For →htmlFor This for is the for on the HTML label that points to the input control. In JSX we use htmlFor instead

<label htmlFor="username"> User name </label> <inputtype="text" id="username" />
Copy the code
  • Hello

    Hello

    the outer {} represents the js syntax, {color: ‘red’} is the object

  • React.Fragment if you have used vue, you should know that the HTML returned by vue must have a root node wrapped around it

<div>
    <div></div>
    <p></p>
</div>
Copy the code

In React, too, if we return multiple divs with flat levels:

But what if we had to use some horizontal elements in a situation where, for style reasons, we didn’t have anything to wrap around div. < react. Fragment> is used to wrap flat elements. This < react. Fragment> is meaningless and acts as a node-closing tag.

let el1 = (
  <React.Fragment>
    <div>{str1}</div>
    <div>{a()}</div>
    <div>{JSON.stringify(obj)}</div>
    <div>{false? <span> </span>:void 0}</div> </ react. Fragment>)Copy the code

So you don’t get an error

In general, React has few apis, and JSX writing is very free. The JS + XML method allows developers with deep JS skills to write JS logic in HTML at will, and they get what they write.

3. The component

In the React project, almost all structural functions can be divided into very detailed components. For example, the commonly used menu bar on a page can be divided into List boxes, List items, ListItem, List links, etc. The advantages are as follows: 1. Reuse 2. Convenient maintenance 3. Improve work efficiency.

React declares components in a function declaration and a class declaration

  • Declaring components functionally declares components as follows
function Build(props) {
  let {title,content} = props;
  return (
    <div>
      <div>{title}</div>
      <div>{content}</div>
    </div>
  )
}

render(<div>
  <Build title="build1" content="content1"></Build>
  <Build title="build2" content="content2"></Build>
  <Build title="build3" content="content3"></Build>
</div>, window.root);
Copy the code

If we just need to display some information on the page and don’t need to control the change, then the function component can simply implement the component definition must be capitalized, and the function component passes the value by defining the property name in the component,
The disadvantage of function components is 1. There is no this 2. There is no state 3. There is no declared period Timers can be used to implement timed changes in values in functional components, such as this example

function Clock(props) {
  return<div> time update: <span>{props. Time}</span></div>}setInterval(()=>{ render(<Clock time={new Date().toLocaleString()} />, window.root); }, 1000).Copy the code
  • The class declaration creates components in the same way that ES6 creates classes. The components declared by the class have state, and the components in our little example are created in the same way after the view is updated with the setState method. Learn to use it by using it

Controlled components and uncontrolled components

Uncontrolled components: The form data is handled by the DOM itself. That is, it is not controlled by setState(). Like traditional HTML form input, the input value displays the latest value (using ref to get the form value from the DOM). In HTML, changes in the values of tags ,

Here we write a small example of an uncontrolled component where the value we enter is displayed by clicking; Uncontrolled components are often used to manipulate the DOM conveniently

import React,{Component} from 'react';
import {render} from 'react-dom'; class UnControl extends Component{ b=React.createRef(); handleClick = () =>{ alert(this.a.value); Alert (this.b.current.value) // alert(this.b.current.value)render() {return (<div>
      <input type="text" id="username" ref={dom=>this.a=dom}/>
      <input type="text" id="password"Ref ={this.b}/> <button onClick={this.handleClick}> </button> </div>)}} render(<UnControl></UnControl>, window.root);Copy the code

Next we will implement a small example like this:

Implement a Comment component similar to the Comment bar below the nuggets. We split this component into the root component App, the List component List, the List item ListItem and the Comment component. During the implementation, we will discuss the way data is passed between components.

4. Methods for updating views

First, instead of splitting the components, we simply built the above example using the Bootstrap UI(NPM install boostrap@3) component for the page structure. In this example, we use AXIos (NPM install AXIos) to request the initial list data, wrapped in a request.js code as follows:

import axios from 'axios';

axios.interceptors.response.use(function (res) {
  if (res.data.code === 0) {
    return res.data.users
  } else {
    return Promise.reject('wrong'); }})export default axios
Copy the code

The requested data format itself is simply:

{
    "code": 0."users": [{"id": 1,
        "avatar": "http://05.imgmini.eastday.com/mobile/20171112/20171112104845_40c4a989ba5a02f512b05336bff309f8_1.jpeg"."username": "Jim"."content": "Hi, your essay is great."
      },
      {
        "id": 2."avatar": "http://05.imgmini.eastday.com/mobile/20171112/20171112104845_40c4a989ba5a02f512b05336bff309f8_1.jpeg"."username": "Jim"."content": "Generally speaking."}}]Copy the code

Then we post our app.js, and we put all the content in app.js, without splitting the components:

import React, { Component } from 'react';
import axios from './request'
import 'bootstrap/dist/css/bootstrap.css'
import './Common/common.css'Class App extends Component {state = {users: [], count: 0, id: 3} increment = () => {this.setState({count: 0, id: 3}) This.state.count + 1})} addComment = (val) => {let id = this.state.id;
        let users = [...this.state.users, { avatar:  "http://05.imgmini.eastday.com/mobile/20171112/20171112104845_40c4a989ba5a02f512b05336bff309f8_1.jpeg", content: val, username: 'Jim', id: id}]; this.setState({ users }); this.state.id+=1; } content = React.createRef(); // Submit data handleSubmit = (e) => {e.preventDefault(); this.addComment(this.content.current.value); } removeById = (id) => {letusers = this.state.users.filter(user=>user.id! ==id); This.setstate ({users})} // get list data asynccomponentDidMount() {
        let users = await axios.get('/users.json');
        this.setState({
            users
        });
    }
    render() {
        return (
          <div className="container">
          <div className="panel panel-danger">
              <div className="panel-heading"> comment </div> <div className="panel-body">
              {
                this.state.users.map((user, index) => {
                  return (
                    <div className="media">
                    <div className="media-left">
                        <img className="avatar" src={user.avatar} />
                    </div>
                    <div className="media-right"> <h3>{user.username} </h3> <div> comment: {user.content}</div> <button className="btn btn-danger"The onClick = {(e) = > {enclosing removeById (. User id)}} > delete < / button > < / div > < / div >)})} < / div > < div className ="panel-bottom">
                <form onSubmit={this.handleSubmit}>
                <textarea className="form-control" required ref={this.content}></textarea>
                <button type="submit"</form> </div> </div> </div> }}export default App;
Copy the code

Effect:


 state = {
        users: [],
        count: 0,
        id: 3
    }
Copy the code

SetState ({users}); state ({users}); Method to update the view. Other operations, such as handleSubmit and removeById, also add and remove data by manipulating state.users.

5. Split components

Given the complexity of a project, we can split the app.js component into a List component, a List item ListItem, and a Comment component so that we don’t have to write the same code all over again when building other structures. We create a components folder under SRC and create list.js listitem.js comment.js

  • List item components:
import React, { Component } from 'react'
export default class ListItem extends Component {
    state = {
        users: [],
        id: 100000
    }
    addComment = (val) => {
        let id = this.state.id;
        let users = [...this.state.users, { avatar:  "http://05.imgmini.eastday.com/mobile/20171112/20171112104845_40c4a989ba5a02f512b05336bff309f8_1.jpeg", content: val, username: 'Jim', id: id}];
        this.setState({
            users
        });
        this.state.id+=1;
    }
    handleClick = (id) => {
        this.props.removeById(id);
    }
    removeById = (id) => {
        let users = this.state.users.filter(user=>user.id!==id); // 排除列表里相同id的,即达到删除的目的
        this.setState({
            users
        })
    }
  render() {
    let {id, avatar, content, username} = this.props;
    return (
        <div className="media">
                    <div className="media-left">
                        <img className="avatar" src={avatar} />
                    </div>
                    <div className="media-right"> <h3>{username} {id}</h3> <div> comment: {content}</div> <button className="btn btn-danger"The onClick = {(e) = > {enclosing handleClick (id)}} > delete < / button > < / div > < / div >)}}Copy the code
  • A list of components
import React, { Component } from 'react'
import ListItem from './ListItem'
export default class List extends Component {
  static props = {
    showComment: true
  }
  render() {
    return (
      <div>
        {
            this.props.users.map((user, index) => {
                return( <ListItem showComment={this.props.showComment} {... user} key={index} removeById={this.props.removeById} addComment={this.props.addComment}></ListItem> ) }) } </div> ) } }Copy the code
  • Comment box component
import React, { Component } from 'react'

export default class Comment extends Component {
    content = React.createRef();
    handleSubmit = (e) => {
        e.preventDefault();
        this.props.addComment(this.content.current.value);
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
            <textarea className="form-control" required ref={this.content}></textarea>
            <button type="submit"</button> </form>)}}Copy the code
  • App. Js into
import React, { Component } from 'react';
import axios from './request'
import 'bootstrap/dist/css/bootstrap.css'
import './Common/common.css'
import Comment from './components/Comment'
import List from './components/List'
import {Provider} from './context'

class App extends Component {
    state = {
        users: [],
        count: 0,
        id: 3
    }
    increment = () => {
        this.setState({
            count: this.state.count + 1
        })
    }
    addComment = (val) => {
        let id = this.state.id;
        let users = [...this.state.users, { avatar:  "http://05.imgmini.eastday.com/mobile/20171112/20171112104845_40c4a989ba5a02f512b05336bff309f8_1.jpeg", content: val, username: 'Jim', id: id}];
        this.setState({
            users
        });
        this.state.id+=1;
    }
    removeById = (id) => {
        console.log(id)

        letusers = this.state.users.filter(user=>user.id! ==id); This.setstate ({users})} async {this.setState({users})} asynccomponentDidMount() {
        let users = await axios.get('/users.json');
        this.setState({
            users
        });
    }
    render() {
        return (
        <Provider value={{increment: this.increment}}>
            <div className="container">
                <div className="panel panel-danger">
                    <div className="panel-heading"> comment </div> <div className="panel-body">
                        <List users={this.state.users} showComment={true} removeById={this.removeById} addComment={this.addComment}></List>
                    </div>
                    <div className="panel-bottom">< br/> <Comment addComment={this.addcomment}></Comment> Number of likes {this.state.count} </div> </div> </div> </Provider>); }}export default App;
Copy the code

So how do we use the users data, removeById and addComment methods we defined earlier on the component? Now let’s explain.

6. Transfer of properties between components

  • The way components interact with data is through property passing, passing property values or methods
  • Child components cannot modify property values directly
  • However, property values can be changed through method calls passed in by the parent component
  • Data transfer is one-way: parent -> child, often referred to as monomial data flow
  • The child component gets the property: ‘this.props. Fn
  • You can usecontextApiImplement cross-component delivery

In the component we split in the previous section, the loop body data source in the list component was changed from this.state.users to this.props. Users, and passed in app.js as

<List users={this.state.users} showComment={true} removeById={this.removeById} addComment={this.addComment}></List>
Copy the code

There is a one-to-one correspondence between incoming and fetch. ListItem (ListItem) ¶ ListItem (ListItem) ¶ ListItem (ListItem) ¶ ListItem (ListItem) ¶ ListItem (ListItem) ¶ ListItem (ListItem) ¶

<ListItem showComment={this.props.showComment} {... user} key={index} removeById={this.props.removeById} addComment={this.props.addComment}></ListItem>Copy the code

In the ListItem component, we wrap the removeById method one more layer

handleClick = (id) => { this.props.removeById(id); }... <button className="btn btn-danger"OnClick = {(e) = > {enclosing removeById (. User id)}} > delete < / button >Copy the code

Here, our deletion method comes from the method passed in by the root component. After the child component gets it, it makes modifications to users, which is also passed in, to achieve the purpose of changing the data. So that’s a simple component pass.

contextApi

If we want to add a “like” function to the list, that is, any list item component can be liked, and the “like” can also collect the total, then if we use parent-child components to pass values, the code may be more cumbersome or error-prone, because there are many levels involved. So we use contextApi to do this (React16.3).

The way to import (in this example, I pulled the import into context.js so I didn’t have to write a deconstruction on every page) :

import React from 'react'
let {Provider, Consumer} = React.createContext();

export {Provider, Consumer}
Copy the code

To use it in a component, after the parent component is introduced, wrap the parent’s return value in a Provider and pass in the value property:

import React, { Component } from 'react';
import {Provider} from './context'Class App extends Component {state = {users: [], count: 0, id: 3} increment = () => {this.setState({count: 0, id: 3}) this.state.count + 1 }) }render() {
        return (
        <Provider value={{increment: this.increment}}>
            <div className="container">
                <div className="panel panel-danger">
                    <div className="panel-heading"> comment </div> <div className="panel-body">
                        <List users={this.state.users} showComment={true} removeById={this.removeById} addComment={this.addComment}></List>
                    </div>
                    <div className="panel-bottom">< br/> <Comment addComment={this.addcomment}></Comment> Number of likes {this.state.count} </div> </div> </div> </Provider>); }}export default App;
Copy the code

In the child component, Consumer needs to be wrapped around the return value (consumption), and the value of value, the property passed in by the Provider, is passed in by the arrow function to call the parent component or the higher component’s property directly from the component.

import React, { Component } from 'react'
import {Consumer} from '.. /context'.export default class ListItem extends Component {
    ...
  render() {
    let {id, avatar, content, username} = this.props;
    return (
        <Consumer>
            {(value)=>{
                return <div className="media">
                    <div className="media-right">... <button className="btn btn-primary"OnClick = {() = > {value. The increment ()}} > good < / button >... </div> </div> }} </Consumer> ) } }Copy the code

conclusion

The above is my summary of how to learn React. I wrote an immature example to practice my React skills. Please forgive me if THERE may be some leaps in expression. Here is the Github code for this small example. If you need to know more about it, you can check it out :code. I hope my article helped you.