在React中,当触发任何变更时如何触发组件所有实例的变更

时间:2019-05-05 08:31:04

标签: reactjs react-component

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

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

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

此图像将更好地解释我要做什么。

sample image

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;

1 个答案:

答案 0 :(得分:1)

您可以使用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