React学习笔记(下)

内容概要:

  • Higher order component
  • Ref
  • context API
  • Http / Ajax / axios
  • Redux


1. Higher-order component

A higher-order component is a function that takes a component and returns a new component.

Example1:

//Inside the withClass
import React from 'react';

// const WithClass = props => (    
//     
{props.children}
// ); //now it is not a Component any more //It is a normal javascript function const withClass = (WrappedComponent, className) => { return props => (
) } export default withClass
// Use the higher order component in App.js
export default withClass(App, styles.App) ;



Example 2:

import React from 'react';
const Aux =  (props) => props.children;
export default Aux
//Use it in App.js
 return (
      
        
        {this.state.showCockpit?  : null}
        {persons}
      
      
    );


2. Ref

Refs stand for references. ref keyword could be used on any element or component.

When to Use Refs:
There are a few good use cases for refs:

  • Managing focus, text selection, or media playback.
  • Triggering imperative animations.
  • Integrating with third-party DOM libraries.

Creating Refs

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return 
; } }



Accessing Refs
When a ref is passed to an element in render, a reference to the node becomes accessible at the current attribute of the ref.

const node = this.myRef.current;



The value of the ref differs depending on the type of the node:

  • When the ref attribute is used on an HTML element, the ref created in the constructor with React.createRef() receives the underlying DOM element as its current property.
  • When the ref attribute is used on a custom class component, the ref object receives the mounted instance of the component as its current.
  • You may not use the ref attribute on function components because they don’t have instances.

current property 在首次mounted时赋值为当前element,在unmounted时重新变为nullref的值在 componentDidMountcomponentDidUpdate之前更新

useRef()
在默认情况下,functional component 中不能使用ref。 然而可以使用 useRef() React Hook 在functional component 中创建并初始化 ref.

const Cockpit = (props) => {
  const toggleBtnRef = useRef(null);

    //useEffect works after every render cycle
    // The functions inside will execute after the JSX loaded
    useEffect(() => {
        toggleBtnRef.current.click();
        
        return () => {
            console.log('[Cockpit.js] cleanup work in useEffect');
        }
    }, []);

  return(
        
); }

以上例子中,使得button按钮在首次render完成后,被默认点击一次。


3. Context API

Say we are in a case where we want to pass a prop from component A at the top to component D at the bottom. And we have components B and C in the middle, but they don't really care about the props, they will just transmit props.

It is useful when you don't want to pass props across multiple layers. It helps you skip the middle components.

import {React} from 'React';

const authContext = React.createContext({
    authenticated: false,
    login: () => {}
});

export default authContext;

React.createContext() 可以创建并初始化context的值,这个值可以是一个 JavaScript Object, 也可以是 number, array, string等等。你可以自定义这个值的有效范围, 让他在React Components中传递。

  • Provider & Consumer
    在App.js中,将需要传递的值赋给在上例中已提前定义好的JS对象。使用 包裹你需要使用此value的内容。
import AuthContext from '../context/auth-context' ;

 
              
          {this.state.showCockpit?  : null}
          {persons}
        

也与之类似,用它包裹相关的代码段,且包装为一个函数。由context传入所需要的数值。

return(
        
... Other content {(context) => }
);



Another Way to use . In this way, we can access the context in life cycle hooks like componentDidMount() exected after render.

In class-base components:

import AuthContext from '../../../context/auth-context';

class Person extends Component{
  static contextType = AuthContext;

    componentDidMount() {
        console.log(this.context.authenticated);
    }
}

render(){    
        return (
            
                {this.context.authenticated ? 

Authenticated!

:

Please Login !

} ... Other content
) }

contextType is a reserved word, you have to write exactly the same.

In functional components, you can use useContext hook to achieve the same effect.

import AuthContext from '../../context/auth-context'

const Cockpit = (props) => {
  const authContext = useContext(AuthContext);
  console.log(authContext.authenticated);

   return(
        
); }


4.Http Request in React

When you send requests to a server, you won't get HTML pages back, instead, you will get JSON data.
Normally, your server is a RESTFUL API, just exposing some API endpoints to which you can send requests.

  • AJAX

  • axios

interceptors: that Axios calls for every request. You can use interceptors to transform the request before Axios sends it, or transform the response before Axios returns the response to your code.
It is useful for setting some common headers like authorization headers or handling errors globally.

// In index.js
axios.interceptors.request.use(request => {
    console.log(request);
    // always need to return the request, otherwise it blocks the request.
    // you can edit the request before you return
    return request;
}, error => {
    console.log(error);
    return Promise.reject(error);
});

axios.interceptors.response.use(response => {
    console.log(response);
    // Edit request config
    return response;
}, error => {
    console.log(error);
    return Promise.reject(error);
})

Removing Interceptors (otherwise could cause leak memory):

var myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
  • fetch()



5. Routing

The basic idea is to load different component codes for different paths.


Routing
  • Implement:
    install react-router-dom, then wrap the component, where you are going to use Router.
import { BrowserRouter } from 'react-router-dom';

class App extends Component {
  render() {
    return (
      
        
); } }


  • Use component.
    import {Route, Link} from 'react-router-dom';

It can be configured with several attributes.

1.path: start with the certain path
2.exact: exactly the same path
3.render: render some JSX code under this path
4.component: render a component under this path

  
  


You can also pass an Object to the to attribute in

  • New Post
    1. pathname: relate to the path you set in . It is always treated as an absolute path.
    2. hash: Used to jump to a certain part of your page, or scroll smoothly there.
    3. search:
      ...



    • 可以使用添加activeStyle attribute 来给Route添加样式。如果不需要样式,使用即可。
  • Home


  • 整体代码:

    import React, { Component } from 'react';
    import {Route, Link} from 'react-router-dom';
    import Posts from './Posts/Posts';
    import NewPost from './NewPost/NewPost';
    import './Blog.css';
    
    class Blog extends Component {
    
        render () {
            return (
                
    {/*

    Home

    }/> */} {/* loading components */}
    ); } } export default Blog;

    运行效果:



    • withRouter High Order Component
      We use the HOC to wrap the export to make the exported component route aware. And it will get the props containing information for the nearest loaded route.
    import {withRouter} from 'react-router-dom';
    


    • Absolute Path vs Relative Path
      An absolute path is always appended to your domain. 在的 to attribute 中, 所有的path都默认为Absolute path.

      Sometimes, you might want to create a relative path instead. This is especially useful if your component is already loaded given a specific path (e.g. posts ) and you then want to append something to that existing path (so that you, for example, get /posts/new ).

      If you're on a component loaded via /posts , to="new" would lead to example.com/new , NOT example.com/posts/new.

      使用以下方法可以获得dynamic path:


    • Route Parameters
      传参(Pass Route Parameters):

      提取参数(extract route parameters):

    But how do you extract search (also referred to as "query") parameters (=> ?something=somevalue at the end of the URL)? How do you extract the fragment (=> #something at the end of the URL)?

    Query Params:
    You can pass them easily like this:

    Go to Start

    or

    Go to Start
    

    React router makes it easy to get access to the search string: props.location.search.

    But that will only give you something like ?start=5

    You probably want to get the key-value pair, without the ? and the = . Here's a snippet which allows you to easily extract that information:

    componentDidMount() {
        const query = new URLSearchParams(this.props.location.search);
        for (let param of query.entries()) {
            console.log(param); // yields ['start', '5']
        }
    }
    

    URLSearchParams is a built-in object, shipping with vanilla JavaScript. It returns an object, which exposes the entries() method. entries() returns an Iterator - basically, a construct which can be used in a for...of... loop (as shown above).

    When looping through query.entries(), you get arrays where the first element is the key name (e.g. start ) and the second element is the assigned value (e.g. 5).

    Fragment:
    You can pass it easily like this:

    Go to Start

    or

    Go to Start
    

    React router makes it easy to extract the fragment. You can simply access props.location.hash.


    • Using Switch
      Switch tells React to only load the first Route that matches from a given set of routes.
     
              
               
               
    
    

    When we wrap our routes within Switch, and the first route that matches a given path will be loaded. After, it will just stop analyzing the routes, it won't render any other route.


    • Nested Route
      It is a condition that you implement a Route inside a component rendered by a Route.
    
    

    Use this.props.match.url dynamically get parent url.


    • Conditional Redirects
    1. Use to redirect.
      Use it as a component. Render it to leave the current page.
    import {Redirect} from 'react-router-dom';
    
    
    1. Use this.props.history.push("path") or this.props.history.replace("path") to redirect.
      Difference: push() function push a new page on the satck, whereas redirect and replace() function replace the current page.


    • Navigation Guard
      It is usually used when you don't know whether the user is authenticated or not. Or in your application, there are some routes that you only allow authenticated users to access.


    • Handle unknown routes 404
     
              
               
               
                

    Not Found

    }/>


    • Lazy Loading

    Only loading the component once you need it.

    Now the thing is whenever you are importing something with import from somewhere.
    you basically inform webpack, the build tool which gets used behind the scenes about this dependency and it will include it in the global bundle, this is its job.

    Now for the lazy loading, this is exactly the opposite of what we want to do, we don't want to include it in the bundle, we want to load it when needed.

    Still, webpack needs to be able to dynamically prepare some extra bundle for this potentially loaded code.

    1. Create a Higher-Order Component:
    import React, {Component} from 'react';
    
    const anycComponent = (importComponent) => {
        return class extends Component{
            state = {
                component: null
            }
    
            componentDidMount(){
                importComponent()
                .then(cmp => {
                    this.setState({component: cmp.default});
                });
            }
    
            render () {
                const C = this.state.component;
    
                return C ?  : null;
            }
        }
    }
    
    export default anycComponent;
    
    1. import the component we want to dynamically load in this HOC.
    import React, { Component } from 'react';
    import {Route, NavLink, Switch} from 'react-router-dom';
    import Posts from './Posts/Posts';
    //import NewPost from './NewPost/NewPost';
    import asyncComponent from '../../hoc/asyncComponent';
    
    const AsyncNewPost = asyncComponent(() => {
        return import('./NewPost/NewPost');
    })
    
    class Blog extends Component {
        render () {
            
    } } export default Blog;



    React 16.0 版本及以上,可用React.lazy()方法引入component,并使用 component 将其包裹:

    import React, { Component, Suspense } from 'react';
    import { BrowserRouter, Route, NavLink } from 'react-router-dom';
    
    import User from './containers/User';
    import Welcome from './containers/Welcome';
    
    const Posts = React.lazy(() => import('./containers/Posts'));
    
    class App extends Component {
      state = { showPosts: false };
    
      modeHandler = () => {
        this.setState(prevState => {
          return { showPosts: !prevState.showPosts };
        });
      };
    
      render() {
        return (
          
            
            {this.state.showPosts ? (
              Loading...
    }> ) : ( )} ); } } export default App;


    6. Redux

    It is a library often used in React projects to manage application state.

    Redux work flow

    There are four stages to building a Redux app:

    1.Visualise the state tree
    2.Design your reducers
    3.Implement Actions
    4.Implement Presentation
























    你可能感兴趣的:(React学习笔记(下))