反应连接的组件在获取数据后不重新渲染

React connected component not rerendering after fetching data

我正在尝试使用 React 和 Redux 渲染 D3 图表。我能够按预期看到从 reducer 返回的数据,即具有 50 个对象的 data 数组。但是在获取数据后不会调用渲染函数。我读过很多关于变异状态的过去问题,但据我所知,当我使用 Object.assign({}, state, data)

时我并没有这样做

reducer 中的控制台日志正在打印正确的数据。

谁能看出我做错了什么?

组件

class D3 extends Component {
    constructor(props) {
        super(props);
    }

    componentDidMount(){
        this.props.dispatch(fetchData());
    }

    randomizeData() {
        this.props.dispatch(randomizeData())
    }

    render() {
        return (
            <div>
                <ScatterPlot {...this.props.data} {...styles} />
                <div className="controls">
                    <button
                        onClick={() => this.randomizeData()}
                    >
                        Randomize Data
                    </button>
                </div>
            </div>
        );
    }
}

const mapStateToProps = (state) => {
    return {
        data: state.data
    }
};

export default connect(mapStateToProps)(D3);

操作

// The number of data points for the chart.
const numDataPoints = 50;

// A function that returns a random number from 0 to 1000.
const randomNum = () => Math.floor(Math.random() * 1000);

// A function that creates an array of 50 elements of (x, y) coordinates.
const randomDataSet = () => {
    return Array.from(Array(numDataPoints)).map(() => [randomNum(), randomNum()]);
};

const requestData = () => ({
    type: 'REQUEST_DATA'
});

const receiveData = json => {
    return ({
    type: 'RECEIVE_DATA',
    data: json,
    receivedAt: Date.now()
})};

export const fetchData = () => (dispatch) => {
    dispatch(requestData());
    dispatch(receiveData(randomDataSet()));
};

export const randomizeData = () => (dispatch) => {
    dispatch(receiveData(randomDataSet()));
};

减速器

const initialState = { data: [] };

const d3 = (state = initialState, action) => {
    switch (action.type) {

    case 'REQUEST_DATA': {
        return Object.assign({}, state, {
            isFetching: true
        });
    }
    case 'RECEIVE_DATA': {
        const result =  Object.assign({}, state, {
            isFetching: false,
            data: action.data,
            lastUpdated: action.receivedAt
        });
        console.log(result)
        return result;
    }

    default: return state;
    }
};

export default d3;

ScatterPlot.jsx

import React from 'react';
import * as d3 from 'd3';
import DataCircles from '../../../molecules/Chart/DataCircles';
import Axis from '../../../molecules/Chart/Axis';

// Returns the largest X coordinate from the data set.
const xMax = data => d3.max(data, d => d[0]);

// Returns the higest Y coordinate from the data set.
const yMax = data => d3.max(data, d => d[1]);

// Returns a function that "scales" X coordinates from the data to fit the chart.
const xScale = props => {
    return d3
        .scaleLinear()
        .domain([0, xMax(props.data)])
        .range([props.padding, props.width - props.padding * 2]);
};

// Returns a function that "scales" Y coordinates from the data to fit the chart.
const yScale = props => {
    return d3
        .scaleLinear()
        .domain([0, yMax(props.data)])
        .range([props.height - props.padding, props.padding]);
};

const ScatterPlot = props => {

    if(props.data){
        const scales = { xScale: xScale(props), yScale: yScale(props) };
        return (
            <svg width={props.width} height={props.height}>
                <DataCircles {...props} {...scales} />
                <Axis ax={'x'} {...props} {...scales} />
                <Axis ax={'y'} {...props} {...scales} />
            </svg>
        );
    } else {
        return null;
    }

};


export default ScatterPlot;

我觉得这里有错字

<ScatterPlot {...this.props} {...styles} />