Как реагировать на изменение всех экземпляров компонента в React, когда срабатывает любое изменение - PullRequest
1 голос
/ 05 мая 2019

Как мне запустить onchange на всех экземплярах компонента в моем приложении? Например:

Я создал раскрывающийся список как компонент (DDComp), который я использую в нескольких местах как дочерний элемент в других компонентах. При изменении этого DDComp он вызывает замену своего родительского компонента. Это отлично работает.

Чего я хочу добиться, так это то, что всякий раз, когда кто-то меняет раскрывающийся список, он должен срабатывать при изменении во всех экземплярах этого 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 Ответ

1 голос
/ 05 мая 2019

Вы можете использовать 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 для получения фактического значения и элементов, а также функцию для изменения этого значения иitems.

Чтобы не писать DropdownConsumer каждый раз, когда вам нужно состояние для раскрывающегося списка, вы можете создать ConnectedDropdown компонент:

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

Отсюда вы можете использовать свойConnectedDropdown в любом месте приложения и убедитесь, что все эти компоненты используют одно и то же состояние.Проверьте DEMO .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...