在React.js中更改状态时从onDragEnd的滑块获取数据

时间:2019-05-08 19:22:12

标签: reactjs material-ui

我有一个可更改状态变量值的滑块:

onChange = (event, value) => {
    this.setState({sliderValue: value,});
};

onDragEnd = (event, value) => {
    this.props.fetchData(value);
};


...


<Slider
   value={this.state.sliderValue}
   min={0}
   max={100}
   step={1}
   onChange={(event, value) => this.onChange(event, value)}
   onDragEnd={(event) => this.onDragEnd(event)}
/>

有时,将setState用于 this.state.sliderValue 会花费一些时间,并且在触发this.props.fetchData(value)*之前,会先使用旧值进行数据提取。

我如何确保正在获取this.state.sliderValue的最后一个值?

2 个答案:

答案 0 :(得分:1)

问题:

状态更新是异步任务。因此,当滑块更改其值时,您要更新sliderValue,然后将状态sliderValue设置为滑块以更新其值,但是当您停止拖动滑块和您的onDragEnd回调函数会收到旧值通知。

解决方案:

在函数中,onDragEnd仅标记必须检索数据。执行fetch所需的值是状态,因此不需要滑块返回的值。

然后,您可以使用componentDidUpdate来获取数据。

代码示例:

onChange = (event, value) => {
    this.setState({sliderValue: value,});
};


componentDidUpdate(prevPros, prevState) {
  // if data must be fetched and my slider value is updated (prev and current match)
  if (this.state.fetchDataEnabled && prevState.sliderValue === this.state.sliderValue) {
    this.props.fetchData(this.state.sliderValue);
    this.setState({fetchDataEnabled: false});
  }
}


<Slider
   value={this.state.sliderValue}
   min={0}
   max={100}
   step={1}
   onChange={(event, value) => this.onChange(event, value)}
   onDragEnd={() => this.setState({fetchDataEnabled: true})}
/>

答案 1 :(得分:0)

我终于可以使用RxJS debounceTime运算符解决问题了:

import {Subject} from "rxjs";
import {debounceTime} from 'rxjs/operators';

let onChange$ = new Subject();

...

    componentDidMount() {
        this.props.getWeightedCriteria(this.props.decisionId);

        const subscription = onChange$
            .pipe(
                debounceTime(500)
            )
            .subscribe(
                data => this.fetchSliderValues(data)
            );

        // prevent memory leaks
        this.setState((prevState) => ({...prevState, subscription}));
    }

    componentWillUnmount() {
        // prevent memory leaks
        this.state.subscription.unsubscribe();
    }

    onChange = (event, value) => {
        onChange$.next(value);
    };

...

使用debounceTime运算符,将在500 ms内保持不变后获取值。然后,不再需要DragEnd方法。

在我有一些反应的经验之后,我了解到您永远不应该相信组件触发特定顺序的事件。