Information transfer mode between React components

Posted by slibob on Wed, 15 Dec 2021 02:21:22 +0100

When talking about React, you will think of a very important idea, that is, the idea of componentization. It will develop reusable parts into components to form relatively independent components. After componentization, you will also ask some questions. How will information be transmitted between components? The following describes the methods of transferring information between components.

There are five ways to transfer information between components:

1. Pass information from (parent component) to (child component)
2. (parent component) transfer information to deeper (child component) > > use (context)
3. Pass information from (child component) to (parent component)
4. Value transfer between components without any nested relationship (for example, value transfer between sibling components)
5. Use react Redux to share state information among components

The following describes in detail two ways of transmitting information in combination with examples.
The following examples are all classic examples. After reading them, I added my personal opinions. I hope they will be helpful to you.

I (parent component) transmits information to (child component) > > > mainly through prop

    Let's look at the following example
//Parent component
var MyContainer = React.createClass({
  getInitialState: function () {
    return {
      checked: false
    };
  },
  render: function() {
    return (
      <ToggleButton text="Toggle me" checked={this.state.checked} />
    );
  }
});
 
// Subcomponents
var ToggleButton = React.createClass({
  render: function () {
    // Value obtained from (parent component)
    var checked = this.props.checked,
        text = this.props.text;
 
    return (
        <label>{text}: <input type="checkbox" checked={checked} /></label>
    );
  }
});

In the above example, the sub component obtains the text value and the checked attribute value through prop; Then, when the sub component wants to get the information of the parent component, it can also be obtained layer by layer through prop. Let's look at the following example.

The example code of the official document is as follows:

       

var Button = React.createClass({
  render: function() {
    return (
      <button style={{background: this.props.color}}>
        {this.props.children}
      </button>
    );
  }
});
 
var Message = React.createClass({
  render: function() {
    return (
      <div>
        {this.props.text} <Button color={this.props.color}>Delete</Button>
      </div>
    );
  }
});
 
var MessageList = React.createClass({
  render: function() {
    var color = "purple";
    var children = this.props.messages.map(function(message) {
      return <Message text={message.text} color={color} />;
    });
    return <div>{children}</div>;
  }
});

In the above example, the first layer component (MessageList) wants to pass the color value to the third layer component (Button) through the second layer component (Message) is delivered. Then it is realized. However, this method is not very elegant. If there are more levels of delivery, the intermediate levels need to be delivered, and the data delivery becomes more cumbersome. Therefore, we will think about whether we can "skip" to obtain data. At this time, we need to use context. It can help you "skip" Pass the data to the deep-seated component you want to pass to.

II (parent component) transfer information to deeper (child component) > > use (context)
Using context, the improved code is as follows:

var Button = React.createClass({
  // The data type of context must be specified
  contextTypes: {
    color: React.PropTypes.string
  },
  render: function() {
    return (
      <button style={{background: this.context.color}}>
        {this.props.children}
      </button>
    );
  }
});
 
var Message = React.createClass({
  render: function() {
    return (
      <div>
        {this.props.text} <Button>Delete</Button>
      </div>
    );
  }
});
 
var MessageList = React.createClass({
  //The parent component needs to define childContextTypes and getChildContext() 
  childContextTypes: {
    color: React.PropTypes.string
  },
  getChildContext: function() {
    return {color: "purple"};
  },
  render: function() {
    var children = this.props.messages.map(function(message) {
      return <Message text={message.text} />;
    });
    return <div>{children}</div>;
  }
});

In the above code, by adding childContextTypes and getChildContext() to the first layer component MessageList (the provider of context), React automatically passes data down, and then any component in the component (that is, any sub component, that is, Button in this example code) can define contextTypes (the data type of context must be specified) access the data in the context. In this way, there is no need to pass through the second layer components.

The parent component that specifies the data and wants to pass the data down should define childContextTypes and getChildContext(); Subcomponents that want to receive data must define contextTypes to use the passed context.

**three.(Child component) passes information to (parent component)

Let's look at the following example**

// Parent component
var MyContainer = React.createClass({
  getInitialState: function () {
    return {
      checked: false
    };
  },
  onChildChanged: function (newState) {
    this.setState({
      checked: newState
    });
  },
  render: function() {
    var isChecked = this.state.checked ? 'yes' : 'no';
    return (
      <div>
        <div>Are you checked: {isChecked}</div>
        <ToggleButton text="Toggle me"
          initialChecked={this.state.checked}
          callbackParent={this.onChildChanged}
          />
      </div>
    );
  }
});
 
// Subcomponents
var ToggleButton = React.createClass({
  getInitialState: function () {
    return {
      checked: this.props.initialChecked
    };
  },
  onTextChange: function () {
    var newState = !this.state.checked;
    this.setState({
      checked: newState
    });
 
    //Here, the information of the child component is passed to the parent component
    this.props.callbackParent(newState);
  },
  render: function () {
    // Value obtained from (parent component)
    var text = this.props.text;
    // Status data of the component itself
    var checked = this.state.checked;
		//The onchange event is used for events triggered after radio boxes and check boxes are changed.
    return (
        <label>{text}: <input type="checkbox" checked={checked}                 onChange={this.onTextChange} /></label>
    );
  }
});

In the above example, the parent component binds callbackParent={this.onChildChanged}, and the child component uses this props. Callbackparent (new state), which triggers the parent's this Onchildchanged method, which in turn passes the data (new state) of the child component to the parent component.
This is actually done by relying on props to pass the reference of the event and through callback.

IV Transfer values between components without any nested relationship (for example, transfer values between sibling components)

If there is no nesting relationship between components and the nesting level of components is deep, how should we transfer information?

Let's take an example

This example needs to introduce a PubSubJS library, through which you can subscribe to information, publish messages and unsubscribe messages.

// Define a container (put ProductSelection and Product components in one container)
var ProductList = React.createClass({
    render: function () {
      return (
        <div>
          <ProductSelection />
          <Product name="product 1" />
          <Product name="product 2" />
          <Product name="product 3" />
        </div>
      );
    }
});
// Product information container for displaying clicks
var ProductSelection = React.createClass({
  getInitialState: function() {
    return {
      selection: 'none'
    };
  },
  componentDidMount: function () {
  	//Subscribe to a message through the PubSub library
    this.pubsub_token = PubSub.subscribe('products', function (topic, product) {
      this.setState({
        selection: product
      });
    }.bind(this));
  },
  componentWillUnmount: function () {
  	//Unsubscribe information when the component is about to be uninstalled
    PubSub.unsubscribe(this.pubsub_token);
  },
  render: function () {
    return (
      <p>You have selected the product : {this.state.selection}</p>
    );
  }
});
 
var Product = React.createClass({
  onclick: function () {
  	//Publish information through PubSub Library
    PubSub.publish('products', this.props.name);
  },
  render: function() {
    return <div onClick={this.onclick}>{this.props.name}</div>;
  }
});

There is no nested relationship between ProductSelection and Product itself, but a sibling level relationship. However, by subscribing to a message in the ProductSelection component and publishing the message in the Product component, the two components are connected again to transmit information. Therefore, according to my personal understanding, when there is no nested relationship between the two components, we should also connect them through some global events, so as to achieve the purpose of transmitting information.

V Using react Redux to share state information among components

Topics: Javascript Front-end React