在 React 中,如何在触发任何 on change 时触发组件的所有实例的 change

In React, how to trigger on change of all instances of a component when any of on change is triggered

如何在我的应用程序中的组件的所有实例上触发 onchange? 例如:

我创建了一个下拉列表作为组件 (DDComp),我在多个位置将其作为其他组件的子组件使用。在更改此 DDComp 时,它会调用其父组件的 onchange。这很好用。

我想要实现的是,每当有人更改下拉列表时,它应该触发页面上该 DDComp 的所有实例的更改。

这张图片将更好地解释我正在尝试做的事情。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import DateRangePicker from 'react-bootstrap-daterangepicker';

import moment from '../../../plugins/moment/moment.js';


class DDComp extends Component {
    constructor(props) {
        super(props);
        this.changeHandler = this.changeHandler.bind(this);

        this.display_value = 'Filters';
    }
    changeHandler(e, picker) {
        if (typeof this.props.onChange === 'function') {
            let start_date = '';
            let end_date = '';

            if(picker.startDate)
                start_date = picker.startDate.format().split('T')[0];

            if(picker.endDate)
                end_date = picker.endDate.format().split('T')[0];

            this.props.onChange(start_date, end_date);
            this.display_value = picker.chosenLabel;
        }
    }
    render() {
        let ranges = {
            "Today": [moment(), moment()],
            "Yesterday": [moment().subtract(1, "day"), moment().subtract(1, "day")],
            "Last 7 days": [moment().subtract(7, "days"), moment().subtract(1, "day")],
            "Last 30 days": [moment().subtract(30, "days"), moment().subtract(1, "day")],
            "This month": [moment().startOf("month"), moment().endOf("month")],
            "Last month": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")],
        };
        return (            
            <div className={"dropdown float-right"}>
                <DateRangePicker applyClass="devcon-dtp" ranges={ranges} onApply={this.changeHandler}>
                    <button className={"dd-ajax-filter btn btn-outline-secondary btn-sm"} type="button">{this.display_value}</button>
                </DateRangePicker>
            </div>
        );
    }
}

export default DDComp;

您可以使用 React Context API 来存储和共享 Dropdown 的状态。

import React from "react";

const DropdownContext = React.createContext({
  dropdownState: {
    value: null,
    items: [],
    setValue: () => {},
    setItems: () => {}
  }
});

export const DropdownContextProvider = ({ children, initialItems }) => {
  const [value, setValue] = React.useState(null);
  const [items, setItems] = React.useState(initialItems);

  return (
    <DropdownContext.Provider
      value={{
        dropdownState: {
          value,
          setValue,
          items,
          setItems
        }
      }}
    >
      {children}
    </DropdownContext.Provider>
  );
};

export const DropdownContextConsumer = DropdownContext.Consumer;

export const Dropdown = ({ value, items, onChange }) => (
  <select value={value} onChange={e => onChange(e.currentTarget.value)}>
    {items.map(item => (
      <option key={item.key} value={item.value}>
        {item.label}
      </option>
    ))}
  </select>
);

您将使用 DropdownConsumer 接收实际值和项目以及更改这些值和项目的函数。

为了不在每次需要下拉状态时都写DropdownConsumer,可以创建一个ConnectedDropdown组件:

export const ConnectedDropdown = () => (
  <DropdownContextConsumer>
    {({ dropdownState }) => (
      <Dropdown
        value={dropdownState.value}
        items={dropdownState.items}
        onChange={dropdownState.setValue}
      />
    )}
  </DropdownContextConsumer>
);

从这里开始,您可以在应用程序的任何地方使用您的 ConnectedDropdown 并确保所有这些组件使用相同的状态。查看 DEMO.