Nextjs使用样式为jsx的React SSR-无法读取未定义的属性'state'

时间:2018-11-16 17:15:58

标签: javascript reactjs next.js

我偶然发现了一个似乎无法解决的问题。我试图在此处搜索解决方案,但无法自救。我是javascript的新手,请多加注意。

问题: 我正在将带有样式化jsx的nextjs(6.1.2)与react(16.5.0)一起使用:

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import Link from 'next/link';

class ProductCard extends Component {
    constructor(props) {
        super(props);
        this.state = {imgLoaded: false};
        this.imgHasLoaded = this.imgHasLoaded.bind(this);
    }

    imgHasLoaded() {
        this.setState({imgLoaded:true})
    }

    render() {
        return (
            <div className="thumbnail-container">
                <div className="loader-box">
                    <img src={require("../static/loading.png")} className="loading-img" />
                </div>
                <img src={this.props.imgSrc} className="main-img" onLoad={this.imgHasLoaded} />
                <div className="thumbnail-text">
                    {this.props.text}
                </div>
                <ul className="item-list">
                    {this.props.links.map(link =>
                        <li className="item">
                            <span className="item-span"> {link.text} </span>
                            {link.subLinks &&
                                <ul className="sub-item-list">
                                    {link.subLinks.map(subLink => <li>{subLink.text}</li>)}
                                </ul>
                            }
                        </li>
                    )}
                </ul>
                <style jsx> {`
                    .thumbnail-container {
                        user-select: none;
                        position: relative;
                        text-align: center;
                        width: 98%;
                        height: 98%;
                        margin: 1%;
                        display: block;
                        border: 0.3px solid black;
                        overflow: hidden;
                        border-radius: 10px;
                        box-shadow: 0 0 20px 0px rgba(0, 0, 0, 0.5);
                        overflow: hidden;
                        align-items: center;
                    }
                    .thumbnail-text {
                        position: absolute;
                        width: 100%;
                        top: 50%;
                        left: 50%;
                        transform: translate(-50%, -50%);
                        color: #ffffff;
                        font-size: 1.8em;
                        background-color: #333;
                        padding: 5px;
                        border-radius: 5px;
                        text-shadow: 1px 1px #000000;
                        text-transform: uppercase;
                        box-shadow: 0 5px 10px 0px rgba(0, 0, 0, 1);
                        transition: all 0.2s ease;
                    }
                    .thumbnail-container:hover .thumbnail-text, .thumbnail-container:focus .thumbnail-text, .thumbnail-container:active .thumbnail-text {
                        top: 0;
                        transform: translate(-50%, 0);
                        background-color: rgba(255, 124, 4, 0.9);
                        color: #000000;
                        text-shadow: none;
                    }
                    .main-img {
                        width: 100%;
                        height: 100%;
                        border-radius: 8px;
                        margin: auto;
                        -webkit-filter: grayscale(40%) contrast(120%) brightness(110%) saturate(120%);
                        -moz-filter: grayscale(40%) contrast(120%) brightness(110%) saturate(120%);
                        filter: grayscale(40%) contrast(120%) brightness(110%) saturate(120%);
                        opacity: ${this.state.imgLoaded ? 1 : 0};
                    }
                    .thumbnail-container:hover .main-img, .thumbnail-container:focus .main-img, .thumbnail-container:active .main-img{
                        -webkit-filter: grayscale(40%) contrast(120%)  saturate(120%) brightness(30%);
                        -moz-filter: grayscale(40%) contrast(120%)  saturate(120%) brightness(30%);
                        filter: grayscale(40%) contrast(120%)  saturate(120%) brightness(30%);
                    }
                    .item-list {
                        display: none;
                        position: absolute;
                        bottom: 0;
                        left: 0;
                        height: calc(100% - 2em);
                        flex-flow: column wrap;
                        justify-content: space-around;
                        list-style-type: none;
                    }
                    .thumbnail-container:hover .item-list, .thumbnail-container:focus .item-list, .thumbnail-container:active .item-list{
                        display: flex;
                    }
                    .item {
                        font-size: 1.3em;
                        display: flex;
                        flex-flow: column wrap;
                    }
                    .item-span {
                        padding-left: 8px;
                        border-bottom: solid #ff7c04;
                        border-left: solid #ff7c04;
                        transition: border-bottom 0.2s ease;
                    }
                    .item:hover .item-span, .item:focus .item-span, .item:active .item-span{
                        border-bottom: none;
                    }
                    .sub-item-list {
                        margin-left: 8px;
                        margin-top: 8px;
                        border-bottom: solid #ff7c04;
                        border-left: solid #ff7c04;
                        height: auto;
                        flex: 0;
                        overflow: hidden;
                        transition: flex 0.2s ease;
                    }
                    .item:hover .sub-item-list, .item:focus .sub-item-list, .item:active .sub-item-list{
                        flex: 1;
                    }
                    .loader-box {
                        position: absolute;
                        top: 50%;
                        left: 50%;
                        transform: translate(-50%, -50%);
                        width: 48px;
                        height: 48px;
                    }
                    .loading-img {
                        -webkit-animation: rotate-scale-up 1s linear infinite both;
                        animation: rotate-scale-up 1s linear infinite both;
                    }

                    @-webkit-keyframes rotate-scale-up {
                      0% {
                        -webkit-transform: scale(1) rotateZ(0);
                                transform: scale(1) rotateZ(0);
                      }
                      50% {
                        -webkit-transform: scale(1.5) rotateZ(180deg);
                                transform: scale(1.5) rotateZ(180deg);
                      }
                      100% {
                        -webkit-transform: scale(1) rotateZ(360deg);
                                transform: scale(1) rotateZ(360deg);
                      }
                    }
                    @keyframes rotate-scale-up {
                      0% {
                        -webkit-transform: scale(1) rotateZ(0);
                                transform: scale(1) rotateZ(0);
                      }
                      50% {
                        -webkit-transform: scale(1.5) rotateZ(180deg);
                                transform: scale(1.5) rotateZ(180deg);
                      }
                      100% {
                        -webkit-transform: scale(1) rotateZ(360deg);
                                transform: scale(1) rotateZ(360deg);
                      }
                    }


                    a {
                        text-decoration: none;
                    }
                    @media only screen and (max-width: 700px) {
                        .thumbnail-container {
                            width: 96%;
                            height: 96%;
                            margin: 2%;
                        }
                        .thumbnail-text {
                            height: 1.5em;
                            font-size: 1em !important;
                        }
                        .item-list {
                            height: calc(100% - 3em) !important;
                        }
                    }
                `}
                </style>
            </div>
        );
    }
}

但是,当使用上面的代码时,我在第26行(其中“ item-list”开始的地方)的渲染函数中得到了“ “无法读取未定义的属性'state'”” 。问题与使用

有关

opacity: ${this.state.imgLoaded ? 1 : 0};

在styled-jsx中,因为如果没有这一行,代码将运行良好。

有趣的是,如果删除“ item-list”及其内容,即使使用

opacity: ${this.state.imgLoaded ? 1 : 0};

很抱歉,这是一件微不足道的事情,或者/并且我忘记了一些基本问题。请按正确的方向推动我

1 个答案:

答案 0 :(得分:0)

好的,我发现我的问题与此处描述的样式化jsx问题有关:

https://github.com/zeit/styled-jsx/issues/486

临时的解决方法是将imgLoaded拉入var,然后在样式化jsx中使用它。

此处类似的示例:https://github.com/zeit/next.js/issues/5735