在 redux saga 请求完成且数据存在后渲染 visx wordcloud 导致 "read-only" 错误
Render visx wordcloud after redux saga request is done and data is present leads to "read-only" error
我尝试使用从我的服务器获得的数据渲染 visx wourdcloud。我用于显示网站的组件如下:
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { withRouter, RouteComponentProps, useParams } from 'react-router';
import WordCloud from '@/components/WordCloud';
import { getAggregations } from '@/selectors';
export interface WordData {
text: string;
value: number;
}
const AggregationShowComponent: React.FC<RouteComponentProps> = ({ history }) => {
const dispatch = useDispatch();
const { id }: { id: string } = useParams();
const { loading, aggregations } = useSelector(getAggregations);
const aggregation = aggregations.find(a => a._id == id);
const words = [
{
text: 'a',
value: 228
},
{
text: 'b',
value: 42
},
];
if (loading) {
return (
<div>Loading</div>
)
}
return (
<div>
{aggregation._id}
<WordCloud
words={aggregation.data}
// words={words}
width={1024}
height={600}
spiral="archimedean"
rotate="0"
/>
<p>
{aggregation.name}
</p>
</div>
)
}
export const AggregationShow = withRouter(AggregationShowComponent);
负责渲染词云的组件如下:
import React, { useState, useEffect } from 'react';
import { Text } from '@visx/text';
import { scaleLog } from '@visx/scale';
import { Wordcloud } from '@visx/wordcloud';
type SpiralType = 'archimedean' | 'rectangular';
export interface WordData {
text: string;
value: number;
}
interface WordCloudProps {
width: number;
height: number;
words: WordData[],
rotate: number,
spiral: SpiralType,
colors: String[],
}
const colors = ["#000000", "#aaaaaa", '#bbbbbb'];
const fixedValueGenerator = () => 0.5;
export default function WordCloud({ words, width, height, rotate = 0, spiral = 'archimedean' }: WordCloudProps) {
const fontScale = scaleLog({
domain: [Math.min(...words.map((w) => w.value)), Math.max(...words.map((w) => w.value))],
range: [10, 100],
});
const fontSizeSetter = (datum: WordData) => fontScale(datum.value);
return (
<>
<Wordcloud
words={words}
width={width}
height={height}
fontSize={fontSizeSetter}
font={'Impact'}
padding={2}
spiral={spiral}
rotate={rotate}
random={fixedValueGenerator}
>
{(cloudWords) =>
cloudWords.map((w, i) => (
<Text
key={w.text}
fill={colors[i % colors.length]}
textAnchor={'middle'}
transform={`translate(${w.x}, ${w.y}) rotate(${w.rotate})`}
fontSize={w.size}
fontFamily={w.font}
>
{w.text}
</Text>
))
}
</Wordcloud>
</>
);
}
如果我尝试使用请求中的数据(在 aggregation.data 中找到),我会在 d3.js 中收到以下错误:
当我使用像第一个代码块中注释掉的行那样的简单静态数据时,它可以毫无问题地工作。仅当当前数据有效时才获取和显示整个数据也只有当我尝试在 wordcloud 中使用来自 http 请求的数据时我才收到错误。
我还尝试克隆传递到 wordcloud 组件中的数据,以确保其中的一些
redux saga 对状态的影响不会导致错误,但错误仍然存在。
另外我也尝试用useEffect等重置数据,但还是没有成功。
我缺少什么部分?是否有 react/d3 的某些部分导致了我不知道的这个问题?有没有办法绕过这个问题?
谢谢
我找到了解决方案。 d3-cloud 修改了 words 数组,这与 redux 存储数据的不变性相冲突。我只是创建了数组的深层副本:
.data.map(w = {...w})
不确定库的任何其他部分是否应该阻止数据编辑,但这对我有用!
我尝试使用从我的服务器获得的数据渲染 visx wourdcloud。我用于显示网站的组件如下:
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { withRouter, RouteComponentProps, useParams } from 'react-router';
import WordCloud from '@/components/WordCloud';
import { getAggregations } from '@/selectors';
export interface WordData {
text: string;
value: number;
}
const AggregationShowComponent: React.FC<RouteComponentProps> = ({ history }) => {
const dispatch = useDispatch();
const { id }: { id: string } = useParams();
const { loading, aggregations } = useSelector(getAggregations);
const aggregation = aggregations.find(a => a._id == id);
const words = [
{
text: 'a',
value: 228
},
{
text: 'b',
value: 42
},
];
if (loading) {
return (
<div>Loading</div>
)
}
return (
<div>
{aggregation._id}
<WordCloud
words={aggregation.data}
// words={words}
width={1024}
height={600}
spiral="archimedean"
rotate="0"
/>
<p>
{aggregation.name}
</p>
</div>
)
}
export const AggregationShow = withRouter(AggregationShowComponent);
负责渲染词云的组件如下:
import React, { useState, useEffect } from 'react';
import { Text } from '@visx/text';
import { scaleLog } from '@visx/scale';
import { Wordcloud } from '@visx/wordcloud';
type SpiralType = 'archimedean' | 'rectangular';
export interface WordData {
text: string;
value: number;
}
interface WordCloudProps {
width: number;
height: number;
words: WordData[],
rotate: number,
spiral: SpiralType,
colors: String[],
}
const colors = ["#000000", "#aaaaaa", '#bbbbbb'];
const fixedValueGenerator = () => 0.5;
export default function WordCloud({ words, width, height, rotate = 0, spiral = 'archimedean' }: WordCloudProps) {
const fontScale = scaleLog({
domain: [Math.min(...words.map((w) => w.value)), Math.max(...words.map((w) => w.value))],
range: [10, 100],
});
const fontSizeSetter = (datum: WordData) => fontScale(datum.value);
return (
<>
<Wordcloud
words={words}
width={width}
height={height}
fontSize={fontSizeSetter}
font={'Impact'}
padding={2}
spiral={spiral}
rotate={rotate}
random={fixedValueGenerator}
>
{(cloudWords) =>
cloudWords.map((w, i) => (
<Text
key={w.text}
fill={colors[i % colors.length]}
textAnchor={'middle'}
transform={`translate(${w.x}, ${w.y}) rotate(${w.rotate})`}
fontSize={w.size}
fontFamily={w.font}
>
{w.text}
</Text>
))
}
</Wordcloud>
</>
);
}
如果我尝试使用请求中的数据(在 aggregation.data 中找到),我会在 d3.js 中收到以下错误:
当我使用像第一个代码块中注释掉的行那样的简单静态数据时,它可以毫无问题地工作。仅当当前数据有效时才获取和显示整个数据也只有当我尝试在 wordcloud 中使用来自 http 请求的数据时我才收到错误。
我还尝试克隆传递到 wordcloud 组件中的数据,以确保其中的一些 redux saga 对状态的影响不会导致错误,但错误仍然存在。 另外我也尝试用useEffect等重置数据,但还是没有成功。
我缺少什么部分?是否有 react/d3 的某些部分导致了我不知道的这个问题?有没有办法绕过这个问题?
谢谢
我找到了解决方案。 d3-cloud 修改了 words 数组,这与 redux 存储数据的不变性相冲突。我只是创建了数组的深层副本:
.data.map(w = {...w})
不确定库的任何其他部分是否应该阻止数据编辑,但这对我有用!