反应连接的组件在获取数据后不重新渲染
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} />
我正在尝试使用 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} />