【问题标题】:Why a state is not resolved as a variable in nextjs为什么状态没有被解析为 nextjs 中的变量
【发布时间】:2019-08-01 03:22:46
【问题描述】:

我正在使用 passportjs 中间件进行身份验证,它可以工作,但是当我尝试在组件中使用用户对象时,该属性未定义,尽管在 _app.js 中传递。

该应用是基于 nextjs 的快速服务器。我知道用户已通过身份验证,因为我可以在服务器中跟踪它,但不能在任何组件中跟踪它。

// _app.js
import React from 'react';
import App, { Container } from 'next/app';
import { ThemeProvider } from '@material-ui/styles';
import theme from '../theme/theme';

class MyApp extends App {
    static async getInitialProps({ Component, ctx }) {
        let pageProps = {};
        if (Component.getInitialProps) {
            pageProps = await Component.getInitialProps(ctx);
        }
        if (ctx.req && ctx.req.session && ctx.req.session.passport) {
            pageProps.user = ctx.req.session.passport.user;
        }
        return { pageProps };
    }

    constructor(props) {
        super(props);
        this.state = {
            user: props.pageProps.user
        };
    }

    render() {
        const { Component, pageProps } = this.props;

        const props = {
            ...pageProps,
            user: this.state.user,
        };

        return (
            <Container>
                <ThemeProvider theme={theme}>
                    <Component {...props} />
                </ThemeProvider>
            </Container>
        );
    }
}

export default MyApp;

Webstorm 指向 user: this.state.user 行,抱怨 unresolved variable user 但我不明白为什么不解析为变量,它是在构造函数中定义的。

编辑:这是 server.js

const express = require("express");
const http = require("http");
const next = require("next");
const session = require("express-session");
const passport = require("passport");
const uid = require('uid-safe');
const authRoutes = require("./auth-routes");
const oAuth2Strategy = require("./lib/passport-oauth2-userinfo");

const dev = process.env.NODE_ENV !== "production";
const app = next({
    dev,
});
const handle = app.getRequestHandler();

app.prepare().then(() => {
    const server = express();

    const sessionConfig = {
        secret: uid.sync(18),
        cookie: {
            maxAge: 86400 * 1000 // 24 hours in milliseconds
        },
        resave: false,
        saveUninitialized: true
    };
    server.use(session(sessionConfig));

    passport.use(new oAuth2Strategy(
        {
            authorizationURL: process.env.REACT_APP_AUTH_URL,
            tokenURL: process.env.REACT_APP_AUTH_TOKEN,
            clientID: process.env.REACT_APP_CLIENT_ID,
            clientSecret: process.env.REACT_APP_SECRET,
            callbackURL: process.env.REACT_APP_CALLBACK,
            userProfileURL: process.env.REACT_APP_OPENID
        },
        function(accessToken, refreshToken, extraParams, profile, done) {
            console.log(profile);
            return done(null, profile);
        }

    ));
    passport.serializeUser((user, done) => done(null, user));
    passport.deserializeUser((user, done) => done(null, user));

    server.use(passport.initialize());
    server.use(passport.session());
    server.use(authRoutes);

    const restrictAccess = (req, res, next) => {
        if (!req.isAuthenticated()) return res.redirect("/login");
        next();
    };

    server.use("/", restrictAccess);
    server.use("/profile", restrictAccess);

    server.get("*", handle);

    http.createServer(server).listen(process.env.PORT, () => {
        console.log(`listening on port ${process.env.PORT}`);
    });
});

编辑 2:感谢@SimplyComplexable,我解决了一些问题。在我的 index.js 中,我可以像这样访问用户道具,例如this.props.user.displayName 没问题。

这行得通:

import Landing from "./Landing"
import React from "react";

class Home extends React.Component {

    render() {
        return (
            <div>
                {this.props.user.displayName}
                <Landing />
            </div>
        )
    }
}

export default Home;

但是,例如,在Landing 组件中,prop.user 是未定义的。也许我没有正确访问或以某种方式传递道具?

class Landing extends React.Component {
    const {user} = this.props;
    return (
        <div>
            ...
    )
}
export default withStyles(useStyles)(Landing);

【问题讨论】:

  • 试试“this.props.pageProps.user”
  • @liskaandar this.props 在构造函数中不可用。
  • ctx.req &amp;&amp; ctx.req.session &amp;&amp; ctx.req.session.passport 真的很真实吗?
  • 您能否在getInitialProps 中进行控制台日志pageProps 并检查该值是否实际被设置?我怀疑@EmileBergeron 想知道的是,如果语句正在评估为真,所以它永远不会被设置。
  • Landing 是一个页面吗?我更新了代码沙箱,以展示如何在页面和组件中获取道具。查看about页面,然后查看索引页面中使用的Landing组件。

标签: javascript reactjs passport.js next.js


【解决方案1】:

基于您现在拥有的代码的问题是,您没有将user 向下传递给Landing 组件。 如果您使用以下更改更新您的主页,那么您的代码应该可以工作。

import Landing from "./Landing"
import React from "react";

class Home extends React.Component {

    render() {
        return (
            <div>
                {this.props.user.displayName}
                <Landing user={this.props.user}/>
            </div>
        )
    }
}

export default Home;

对于用户来说,这对于context 来说是一个很好的机会,这样您就不必将用户属性明确地传递给每个组件。 这是一个简单的例子:

import Landing from "./Landing"
import React from "react";

export const UserContext = React.createContext({});

class Home extends React.Component {

    render() {
        return (
            <div>
                {this.props.user.displayName}
                <UserContext.Provider value={this.props.user}>
                  <Landing user={this.props.user}/>
                </UserContext.Provider>
            </div>
        )
    }
}

export default Home;
import React from 'react';
import UserContext from './Home';

const Landing = () => {
    const user = React.useContext(UserContext);
    return (
      <div>
        {user.displayName}
      </div>
    )
}
export default withStyles(useStyles)(Landing);

【讨论】:

    猜你喜欢
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    相关资源
    最近更新 更多