在AJAX请求中反应useState()永远不会更改组件状态

时间:2019-09-06 07:29:46

标签: javascript reactjs react-hooks

我有一个react组件,可让您选择要绘制的数据(基于过滤器和数据类型),然后向服务器请求该数据,然后使用服务器响应来创建绘制。简化版本如下:

function Trend(props) {
    const [dataTypes, setDataTypes] = useState([]);
    const [selectedFilter, selectFilter] = useState(null);
    const [selectedDataTypes, selectDataTypes] = useState([]);
    const [plotData, setPlotData] = useState([]);
    const [revision, setRevision] = useState(0);

    // Whenever the plot data type or filter changes, we have to re-calculate the plot data
    useEffect(() => {
        if (selectedDataTypes.length > 0) {
            client.find('plots/trends/series', {fields: JSON.stringify(selectedDataTypes), filter: selectedFilter})
                .then(data => {
                    console.log('New state!');
                    setPlotData(data.map(datum => datum.toJSON()));
                    setRevision(rev => rev + 1);
                })
        }
    }, [selectedDataTypes, selectedFilter]);

    // When we first create the component, request the data types that could be plotted
    useEffect(() => {
        client.find('data_types')
            .then(resources => {
                setDataTypes(resources.map(resource => resource.get('key')));
            })
    }, []);

    // The template
    return (
        <Plot
            revision={revision}
            data={plotData}
            useResizeHandler={true}
            layout={{
                autosize: true
            }}
            style={{
                width: '100%',
                height: '100%'
            }}
        />
    );

}

尤其是,plotData的值是Plotly data series的数组,每个数组都是一个复杂的嵌套结构。通常,这由3个不同的系列组成,因此plotData = [{}, {}, {}]

当我更新selectedFilter时,确实发送了AJAX请求,并且可以在服务器上看到返回了新数据。此外,“新状态!”消息已记录。但是,plotData状态不会改变。甚至在此调用之后的几秒钟,如果我检查devtools,我仍然可以看到状态没有改变。

但是,修订号确实发生了变化。但这是简单得多的数据,它是整数,而不是对象数组。

这与我正在更改AJAX响应中的状态有关吗?还是我的plotData太复杂了,React没意识到它和以前有什么不同?这似乎很有可能,因为在我更改过滤器后, 90%的返回数据是相同的。 React diffing算法不能在这里分辨出差异吗?

1 个答案:

答案 0 :(得分:-1)

一种解决方案是使用Axios库:

useEffect( () => {
         const callAPI = async () => {
             const res = await Axios.post('plots/trends/series', {
                    params: {fields: JSON.stringify(selectedDataTypes), filter: selectedFilter}
              //just play with response here and update state using hooks
                    }
         }
         if (selectedDataTypes.length > 0) {
             callAPI();
         }   
        }, [selectedDataTypes, selectedFilter]);