node.js - 在 React 组件的 setState 中使用 Math.random 时组件渲染不正确

标签 node.js reactjs styled-components next.js

目的是显示对象列表中的项目,但在每次页面刷新时,应从列表中随机选择该项目。这里,Testimonials 是列表,我想显示此列表中的任何随机项目。如果我使用常量,它就可以正常工作。当我使用随机函数时,它不会显示正确的图像及其关联的项目消息。

我使用 React 16、Next.js、样式组件作为技术。

问题出在员工部分的渲染中。控制台显示警告为

warning.js?6327:33 警告:Propsrc不匹配。服务器:“/static/images/testimonials/2.jpg” 客户端:“/static/images/testimonials/5.png”

这是我的代码

import {Component} from 'react';

import Row from '../../../common-util/row';
import Col from '../../../common-util/col';

import {Container, Content, Image, StyledCol, Statement, Title, Designation, Heading, Arrow} from './styles';

const Testimonials = [{
    name: 'ACX',
    role: 'XYZ',
    image: '/static/images/testimonials/1.jpeg',
    message: 'KL DSAD E'
}, {
    name: 'HJK',
    role: 'Growth Hacker',
    image: '/static/images/testimonials/2.jpg',
    message: 'JKLASD ASDA'
}, {
    name: 'ZXCV',
    role: 'Product Manager',
    image: '/static/images/testimonials/3.jpg',
    message: 'KKK'
}, {
    name: 'UIP',
    role: 'Data Integrity',
    image: '/static/images/testimonials/4.JPG',
    message: 'LOPO'
}, {
    name: 'NMa',
    role: 'Sales Evangelist',
    image: '/static/images/testimonials/5.png',
    message: 'KK D D D'
}];

export default class Employees extends Component {

    constructor(props) {
        super(props);
        this.state = {
            currentIndex: parseInt((Math.random()*10))%5,
        };
    }

    render() {
        let {currentIndex} = this.state;
        return (
            <Container>
                <Content>
                    <Title>Our employees say...</Title>
                </Content>
                <Row>
                    <Col xs={1} sm={1} md={2} lg={2}>
                        <Arrow className={currentIndex === 0 ? 'disabled' : ''} onClick={this.handleClick.bind(this, 'DECREMENT')}>{'<'}</Arrow>
                    </Col>
                    <Col xs={10} sm={10} md={8} lg={8}>{this.currentItem(currentIndex)}</Col>
                    <Col xs={1} sm={1} md={2} lg={2}>
                        <Arrow className={currentIndex === Testimonials.length - 1 ? 'disabled' : ''} onClick={this.handleClick.bind(this, 'INCREMENT')}>{'>'}</Arrow>
                    </Col>
                </Row>
            </Container>
        );
    }

    currentItem(currentIndex) {
        const item = Testimonials[currentIndex];
        return (
            <Row>
                <StyledCol xs={4} md={4} lg={3}>
                    <Image src={item.image} alt={item.name} />
                </StyledCol>
                <Col xs={8} md={8} lg={9}>
                    <Statement>{item.message}</Statement>
                    <Heading className='font-Bold'>{item.name},</Heading>
                    <Designation className='font-DemiBold'>{item.role}</Designation>
                </Col>
            </Row>
        );
    }

    handleClick(type: string) {
        let {currentIndex} = this.state;
        switch (type) {
            case 'DECREMENT':
                this.setState({
                    currentIndex: currentIndex - 1
                });
                break;
            case 'INCREMENT':
                this.setState({
                    currentIndex: currentIndex + 1
                });
                break;
            default:

        }
    }
}

对应的样式为

import styled from 'styled-components';

import Col from '../../../common-util/col';
import Grid from '../../../common-util/grid';
import H4 from '../../../common-util/headers/h4';
import H5 from '../../../common-util/headers/h5';

export const Container = styled(Grid)`
    padding-bottom: 20px;
`;

export const Content = styled.div`
    display: flex;
    flex-flow: row wrap;
    width: 100%;
    justify-content: center;
    margin-bottom: 20px;
`;

export const Title = styled.h1`
    font-size: 42px;
    line-height: 1.0;
    letter-spacing: -0.3px;
    text-align: justify;
    font-weight: 500;
`;

export const Image = styled.img`
    width: 100%;
`;

export const Statement = styled.p`
    padding: 15px 20px;
    background: url(/static/images/svg/top-left-bg.svg) top left no-repeat, url(/static/images/svg/bottom-right-bg.svg) bottom right no-repeat;
    background-size: 20px;
    line-height: 2.3;
    letter-spacing: -0.2px;
    font-size: 16px;
    margin: 0
`;

export const Heading = H4.extend`
    color: #4990e2;
    text-align: left;
    font-weight: bold;
    line-height: 1.2;
    margin-bottom: 5px;
    margin-left: 20px;
`;

export const Designation = H5.extend`
    text-align: left;
    font-weight: 600;
    line-height: 1.22;
    letter-spacing: -0.2px;
    margin-top: 0;
    margin-left: 20px;
`;

export const Arrow = styled.div`
    margin: auto;
    color: grey;
    font-size: 20px;
    font-weight:lighter;
    cursor: pointer;
    &:hover {
        font-size: 22px;
    }

    &.disabled {
        pointer-events: none;
        &:hover {
            font-size: 20px;
        }
    }
`;

export const StyledCol = Col.extend`
    margin: auto;
`;

最佳答案

这就是问题所在。

this.state = {
   currentIndex: parseInt((Math.random()*10))%5,
};

这将在服务器和浏览器中调用,导致渲染标记不匹配。

您可以通过确保仅在浏览器中调用 random 来解决此问题:

this.state = {
  currentIndex: 0,
};

componentDidMount(){
  this.setState({ currentIndex: parseInt((Math.random()*10))%5 })
}

关于node.js - 在 React 组件的 setState 中使用 Math.random 时组件渲染不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50186584/

相关文章:

Javascript - 子项下的状态变化不会持续存在于父项中

css - 事件触发样式的组件CSS更改

css - 如何防止 SVG 线条的粗细不一致和间隙?

javascript - 无法使用异步 waterfall 运行 parse-csv 函数

sql - TypeORM 限制不起作用,无论设置多少限制,查询都会返回数组中的一个元素?

javascript - 找不到全局定义的变量

node.js - 使用 REST 进行环回电子邮件验证(其中配置了所需的 verifyOptions)

javascript - ReactJS 在 if-else 条件语句中调用其他组件

javascript - 为什么 React App 的 redux 情况下 IndexOf(Object) 可以工作?

javascript - react 单选按钮 : checked cycle not aligned