[英]React - refractor state in a component
I have this component that populates logo into a grid system.我有这个组件可以将徽标填充到网格系统中。 It's getting 2 props which are
grid
- takes in logos and limit
- number of logos shown.它得到 2 个道具,它们是
grid
- 接受徽标和limit
- 显示的徽标数量。
type Props = {
grid: [],
limit: number,
};
type State = {
grid: any,
queue: any,
};
class LogoGrid extends Component<Props, State> {
state = {
grid: Object.keys(this.props.grid).map(name => ({name, key: name})).slice(0, this.props.limit),
queue: Object.keys(this.props.grid).map(name => ({name, key: name})).slice(this.props.limit, Object.keys(this.props.grid).length),
};
componentDidMount() {
this.interval = setInterval(this.updateQueue, SWAP_INTERVAL);
}
componentWillUnmount() {
clearInterval(this.interval);
}
getRandomInt = (min: number, max: number) => Math.floor((Math.random() * (max - min)) + min);
updateQueue = (): void => {
const { limit } = this.props;
const grid = [...this.state.grid];
const queue = [...this.state.queue];
const replaceIndex = this.getRandomInt(0, limit);
const removedItem = grid.splice(replaceIndex, 1, queue.shift());
queue.push(removedItem[0]);
this.setState({ grid, queue });
}
render() {
const { grid } = this.state;
return (
<div className={css.container}>
{grid.map((item, i) => (
<CSSTransitionGroup
transitionName={css}
transitionEnterTimeout={SWAP_INTERVAL - 100}
transitionLeaveTimeout={SWAP_INTERVAL - 100}
>
<Logo key={i} name={item.name} color="white" className={css.logo}/>
</CSSTransitionGroup>
))}
</div>
);
}
}
export default LogoGrid;
In the parent component it would be used as below:在父组件中,它将按如下方式使用:
<LogoGrid grid={rawLogos} limit={12} />
rawLogos
in this case is just js file of logos like below:在这种情况下,
rawLogos
只是徽标的 js 文件,如下所示:
const url = (filename) => `${process.env.S3_LOGOS_BASE_URL}/logo-${filename}`;
export default {
'26grains': url('26grains.svg'),
...
...
};
My question is how can I simplify/refractor the LogoGrid component even further especially the way state
is written.我的问题是如何进一步简化/折射 LogoGrid 组件,尤其是
state
的编写方式。
UPDATE:更新:
I tried doing this way but getting an error: Uncaught TypeError: Cannot read property 'map' of undefined
我尝试这样做但出现错误:
Uncaught TypeError: Cannot read property 'map' of undefined
state = {
grid: this.gridItems,
queue: this.queueItems,
};
gridItems = () => {
const logoGrid = Object.keys(this.props.grid).map(name => ({name, key: name})).slice(0, this.props.limit);
this.setState({grid: logoGrid})
}
queueItems = () => {
const queueGrid = Object.keys(this.props.grid).map(name => ({name, key: name})).slice(this.props.limit, Object.keys(this.props.grid).length);
this.setState({queue: queueGrid})
}
You can't set the state while initializing it.您不能在初始化时设置状态。
You can see an example here: https://codesandbox.io/s/reverent-hill-vvet2你可以在这里看到一个例子: https ://codesandbox.io/s/reverent-hill-vvet2
Or here:或者在这里:
const items = ["hi", "test", "3"];
class MyClass extends React.Component {
state = {
items: []
};
componentDidMount() {
this.setItems();
}
setItems() {
console.log(this.props.items);
const items = this.props.items.map(i => <p>{i}</p>);
console.log(items);
this.setState({
items
});
}
render() {
return <div>{this.state.items}</div>;
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<MyClass items={items} />, rootElement);
Solution:解决方案:
Set your state AFTER initializing the state with componentDidMount
like in the example.像示例中一样,在使用
componentDidMount
初始化状态后设置状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.