在 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.
如何在我的应用程序中的组件的所有实例上触发 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.