Refactor Listview to solve a bug

Summary:
There was a bug in ListView where the selected items where not getting updated.

Bug

In the following video I have selected Inspector and logs plugin from export drop down. When I click on litho support form it should select the default plugins which is Inspector, Mobile Config and Logs. But it only shows Inspector and Logs selected

{F226900949}

To fix it:

I call the callback `onChange` when the listview's row get updated, which will updates the props of the ListView component and hence rerendering it with updated selected rows.

Reviewed By: mweststrate

Differential Revision: D19518762

fbshipit-source-id: 39367590cbdc1d6f88afb467b17b71e13703bde3
This commit is contained in:
Pritesh Nandgaonkar
2020-01-23 07:38:35 -08:00
committed by Facebook Github Bot
parent 426d17b08d
commit 032b594221
2 changed files with 47 additions and 50 deletions

View File

@@ -41,7 +41,7 @@ type StateFromProps = {
}; };
type DispatchFromProps = { type DispatchFromProps = {
selectedPlugins: (payload: Array<string>) => void; setSelectedPlugins: (payload: Array<string>) => void;
setActiveSheet: (payload: ActiveSheet) => void; setActiveSheet: (payload: ActiveSheet) => void;
setExportDataToFileActiveSheet: (payload: { setExportDataToFileActiveSheet: (payload: {
file: string; file: string;
@@ -57,32 +57,43 @@ const Container = styled(FlexColumn)({
maxHeight: 700, maxHeight: 700,
}); });
class ExportDataPluginSheet extends Component<Props> { type State = {
render() { availablePluginsToExport: Array<string>;
const { };
plugins,
pluginStates, class ExportDataPluginSheet extends Component<Props, State> {
pluginMessageQueue, state: State = {availablePluginsToExport: []};
onHide, static getDerivedStateFromProps(props: Props, _state: State) {
selectedClient, const {plugins, pluginStates, pluginMessageQueue, selectedClient} = props;
} = this.props; const availablePluginsToExport = getActivePersistentPlugins(
const onHideWithUnsettingShare = () => {
this.props.unsetShare();
onHide();
};
const pluginsToExport = getActivePersistentPlugins(
pluginStates, pluginStates,
pluginMessageQueue, pluginMessageQueue,
plugins, plugins,
selectedClient, selectedClient,
); );
return {
availablePluginsToExport,
};
}
componentDidMount() {
if (this.props.plugins.selectedPlugins.length <= 0) {
this.props.setSelectedPlugins(this.state.availablePluginsToExport);
}
}
render() {
const {onHide} = this.props;
const onHideWithUnsettingShare = () => {
this.props.unsetShare();
onHide();
};
return ( return (
<Container> <Container>
<ListView <ListView
type="multiple" type="multiple"
title="Select the plugins for which you want to export the data" title="Select the plugins for which you want to export the data"
onSelect={selectedArray => { onSubmit={() => {
this.props.selectedPlugins(selectedArray);
const {share} = this.props; const {share} = this.props;
if (!share) { if (!share) {
console.error( console.error(
@@ -107,18 +118,18 @@ class ExportDataPluginSheet extends Component<Props> {
} }
} }
}} }}
elements={pluginsToExport} onChange={selectedArray => {
selectedElements={pluginsToExport.reduce((acc, plugin) => { if (selectedArray.length > 0) {
if ( this.props.setSelectedPlugins(selectedArray);
plugins.selectedPlugins.length <= 0 || } else {
plugins.selectedPlugins.includes(plugin) this.props.setSelectedPlugins(
) { this.state.availablePluginsToExport,
acc.add(plugin); );
} }
return acc; }}
}, new Set([]) as Set<string>)} elements={this.state.availablePluginsToExport}
selectedElements={new Set(this.props.plugins.selectedPlugins)}
onHide={onHideWithUnsettingShare} onHide={onHideWithUnsettingShare}
showNavButtons={true}
/> />
</Container> </Container>
); );
@@ -145,7 +156,7 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
}; };
}, },
(dispatch: Dispatch<Action<any>>) => ({ (dispatch: Dispatch<Action<any>>) => ({
selectedPlugins: (plugins: Array<string>) => { setSelectedPlugins: (plugins: Array<string>) => {
dispatch(actionForSelectedPlugins(plugins)); dispatch(actionForSelectedPlugins(plugins));
}, },
setActiveSheet: (payload: ActiveSheet) => { setActiveSheet: (payload: ActiveSheet) => {

View File

@@ -33,11 +33,11 @@ type SubType =
}; };
type Props = { type Props = {
onSelect: (elements: Array<string>) => void; onSubmit?: () => void;
onChange: (elements: Array<string>) => void;
onHide: () => any; onHide: () => any;
elements: Array<string>; elements: Array<string>;
title?: string; title?: string;
showNavButtons: boolean;
} & SubType; } & SubType;
const Title = styled(Text)({ const Title = styled(Text)({
@@ -113,16 +113,12 @@ class RowComponent extends Component<RowComponentProps> {
export default class ListView extends Component<Props, State> { export default class ListView extends Component<Props, State> {
state: State = {selectedElements: new Set([])}; state: State = {selectedElements: new Set([])};
static getDerivedStateFromProps(props: Props, state: State) { static getDerivedStateFromProps(props: Props, _state: State) {
if (state.selectedElements.size > 0) {
return null;
}
if (props.type === 'multiple') { if (props.type === 'multiple') {
return {selectedElements: props.selectedElements}; return {selectedElements: props.selectedElements};
} else if (props.type === 'single') { } else if (props.type === 'single') {
return {selectedElements: new Set([props.selectedElement])}; return {selectedElements: new Set([props.selectedElement])};
} }
return null; return null;
} }
@@ -138,21 +134,17 @@ export default class ListView extends Component<Props, State> {
} else { } else {
if (selected) { if (selected) {
selectedElements = new Set([...this.state.selectedElements, id]); selectedElements = new Set([...this.state.selectedElements, id]);
this.setState({ this.props.onChange([...selectedElements]);
selectedElements: selectedElements,
});
} else { } else {
selectedElements = new Set([...this.state.selectedElements]); selectedElements = new Set([...this.state.selectedElements]);
selectedElements.delete(id); selectedElements.delete(id);
this.setState({selectedElements}); this.props.onChange([...selectedElements]);
} }
} }
if (!this.props.showNavButtons) {
this.props.onSelect([...selectedElements]);
}
}; };
render() { render() {
const {onSubmit} = this.props;
return ( return (
<Container> <Container>
<FlexColumn> <FlexColumn>
@@ -170,20 +162,14 @@ export default class ListView extends Component<Props, State> {
})} })}
</RowComponentContainer> </RowComponentContainer>
</FlexColumn> </FlexColumn>
{this.props.showNavButtons && ( {onSubmit && (
<Padder paddingTop={8} paddingBottom={2}> <Padder paddingTop={8} paddingBottom={2}>
<FlexRow> <FlexRow>
<Spacer /> <Spacer />
<Button compact padded onClick={this.props.onHide}> <Button compact padded onClick={this.props.onHide}>
Close Close
</Button> </Button>
<Button <Button compact padded type="primary" onClick={onSubmit}>
compact
padded
type="primary"
onClick={() => {
this.props.onSelect([...this.state.selectedElements]);
}}>
Submit Submit
</Button> </Button>
</FlexRow> </FlexRow>