1 Parent-child Communication
-
Add variables of the parent component to the child component tag in the parent component. Methods are accessible to the child component in the form of properties
-
Access the corresponding variable or method in the child component through the this.props. Property name
-
Methods should be defined as arrow functions to avoid confusing this pointing to methods called by different components
// Take todos as an example / / the parent component import React, { Component } from 'react' import AddItem from './AddItem' import Todolist from './Todolist' class Content extends Component { constructor(props) { super(props) this.state = {// Variables in the parent component value: ' '.arrList: []}}// Define the method // Use the setState function to modify variables in state, avoiding direct manipulation of variables in state // In order for the child to call the parent method without changing the this reference, the method should be defined as an arrow function handleChange = (value) = > { this.setState({// Async operation, but synchronous operation if used in timer value }) } handleClick = () = > { this.setState({ arrList: [...this.state.arrList, this.state.value], value: ' ' }) } deleteClick = (id) = > { let temparr = this.state.arrList temparr.splice(id,1) this.setState({ arrList: temparr }) } render() { return ( <div> <AddItem value = {this.state.value} handleChange = {this.handleChange} handleClick = {this.handleClick} /> <Todolist arrList = {this.state.arrList} deleteClick = {this.deleteClick} /> </div>)}}export default Content // Child AddItem import React, { Component, Fragment } from 'react' class AddItem extends Component { getInpValue = (e) = > { this.props.handleChange(e.target.value) } render() { return ( <Fragment> <input type = "text" value = {this.props.value} onChange = {this.getInpValue} /> <button onClick = {this.props.handleClick}>Add tasks</button> </Fragment>)}}export default AddItem // Child Todolist import React, { Component } from 'react' class Todolist extends Component { // If the parent component method needs to pass parameters, it should be called in the child component method, passing parameters to the child component method with the bind binding parameter // While it is possible for a parent component to define an arrow function for a method, it is more reliable for a child component to bind the method deleteItem (i) { this.props.deleteClick(i) } render() { return ( <ul> { this.props.arrList.map((item,index) => { return ( <li key = {index}> {item} <span onClick = {this.props.deleteClick.bind(this,index)}>X</span> </li>)})}</ul>)}}export default Todolist Copy the code
2 Use context to communicate across components
-
The function of the context
- React has no event bus like vUE to solve this problem
- We can only do this with their common parent component, replacing the non-parent-child relationship with a multi-dimensional parent-child relationship
- React provides the Context API for cross-component communication. The React 16.3 contextAPI is better than the contextAPI
-
Method of use
-
React.createcontext () We need to use createContext to create the context
-
It returns an object that has two components in it
- Provider: sets the share status and method
- Pass it by value
- Consumer: Receives the shared state or method
- All components wrapped by the Provider component can be received by the Consumer
- The Consumer component must return a function inside that accepts the state and methods passed to it by the Provider
- Provider: sets the share status and method
-
Example: buttons implement add/subtract
- index.js
// index.js import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import CountProvider from './context' // If there is any content in the component tag, it is not automatically parsed. You need to use this.props. Children inside the component ReactDOM.render( ( <CountProvider> <App /> </CountProvider> ), document.getElementById('root')); Copy the code
-
context.js
import React, { createContext, Component, Fragment } from 'react' // Fragment does not generate DOM tags. It is usually used as a root tag. You can also use <> instead const {Consumer, Provider} = createContext() class CountProvider extends Component { constructor(props) { super(props) this.state = { num: 10 } } addNum = () = > { this.setState({ num: this.state.num + 1 }) } minusNum = () = > { this.setState({ num: this.state.num - 1})}// This.props. Children gets the APP component, so any component used in the APP component can be received by the Consumer render() { return ( <Fragment> <Provider value = {{ num: this.state.num.addNum: this.addNum.minusNum: this.minusNum}} > {this.props.children} </Provider> </Fragment>)}}// export export syntax is available // export let/const Export function () {} // export {variable name} // export default can export variables directly, but can only be used once export default CountProvider export {Consumer, Provider} Copy the code
-
App.js
import React, { Component } from 'react' import CountButton from './components/button' import Count from './components/count' class App extends Component { render () { return ( <div> <CountButton type='add'>+</CountButton> <Count /> <CountButton type='minus'>-</CountButton> </div>)}}export default App; Copy the code
-
/count/index.js
import React, { Component } from "react"; import {Consumer} from '.. /.. /context' class Count extends Component { render() { return ( <Consumer> { ({num}) => { return ( <span>{num}</span>)}}</Consumer>)}}export default Count Copy the code
-
/button/index.js
import React, { Component } from 'react' import { Consumer } from '.. /.. /context' class CountButton extends Component { render() { return ( <Consumer> { ({addNum, minusNum})=>{ const setFunc = this.props.type === 'add' ? addNum : minusNum return ( <button onClick={setFunc}> {this.props.children} </button>)}}</Consumer>)}}export default CountButton Copy the code
-
3 ref communication
-
Applicable scenario
- Control of DOM element focus, content selection, or media playback
- Trigger animation effects by controlling DOM elements
- Integrate third-party DOM libraries
-
Avoid the use of
- Avoid using Refs to do anything that can be done with declarative implementations
- For example, to avoid exposing open(), show(), hide(), and close() methods inside Dialog, Loading, and Alert components, it is better to control them through isXX properties
-
Use restrictions
-
Refs (createRef, useRef, callback Ref) is not supported inside function components
-
You cannot use the ref attribute on a function component because the function component has no instance
-
UseRef is limited to use within function components
-
3.1 Refs of String type
-
Sets the REF attribute on the element or component label
<button ref = 'btnRef' onClick = {this.handleClick}>dianwo</button> <Son ref = 'sonRef' /> Copy the code
-
This. Refs gets all elements or component instances with the ref attribute set
- For example, states and methods in Son components can be accessed through this.refs.sonref
- Use this.refs.btnref to manipulate the real Button DOM
-
Outdated APIS are recommended to be replaced with callback functions or createRef APIS
-
Function components are not supported internally
3.2 createRef API
-
Introduced in act16.3
-
Create Refs with react.createref () and attach them to the React element via the ref attribute. Typically in constructors, Refs are assigned to instance properties for reference throughout the component.
-
When a ref is passed to an element in render, a reference to that node can be accessed in the ref’s current property
-
The value of ref varies depending on the type of node
-
When the ref attribute is used for HTML elements, the ref created with react.createref () in the constructor receives the underlying DOM element as its current attribute
-
When the REF attribute is used for a custom class component, the REF object receives the component’s mounted instance as its current attribute
-
Cannot be used on function components
ref
Property because the function component has no instance
this.sonRef = createRef()
<Son ref = {this.sonRef} />
this.sonRef.current
Copy the code
3.3 useRef API
-
UseRef was introduced in Act 16.8 and can only be used in function components
-
Create Refs with React.useref () and attach them to the React element via the ref attribute
-
The ref object returned remains constant throughout the life of the component
-
When a ref is passed to the React element, a reference to that node can be accessed in the current attribute of the ref
import React from 'react';
export default function MyInput(props) {
const inputRef = React.useRef(null);
React.useEffect(() = > {
inputRef.current.focus();
});
return (
<input type="text" ref={inputRef} />)}Copy the code
3.4 Refs in callback form
-
In earlier versions of React, we recommended refs in the form of callbacks
-
This gives us more fine-grained control over when Refs are set and released
-
Pass the callback function data to the REF attribute of the React element. This function takes a React component instance or AN HTML DOM element as an argument and mounts it to the instance properties
-
React calls the REF callback and passes in the DOM element (or React instance) when the component is mounted, and calls it and passes in NULL when it is unmounted. React ensures that the Refs are up to date before componentDidMount or componentDidUpdate is triggered
import React from 'react';
export default class MyInput extends React.Component {
constructor(props) {
super(props);
this.inputRef = null;
this.setTextInputRef = (ele) = > {
this.inputRef = ele; }}componentDidMount() {
this.inputRef && this.inputRef.focus();
}
render() {
return (
<input type="text" ref={this.setTextInputRef}/>)}}Copy the code
All you want to know about Refs is here — Liu Xiaoxi
The foundation determines the future, one step at a time