问题描述
我对如何构建我的react/graphql(apollo)应用程序有点困惑,直到用户对用户进行认证/登录.
目前我有一个:
class App extends Component { render() { return ( <ApolloProvider client={client}> <Provider store={store}> <Router> <div> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/login">Log In</Link></li> <li><Link to="/signup">Sign Up</Link></li> </ul> <AuthenticatedRoute exact path="/" component={HomePage} /> <Route path="/login" component={LoginPage} /> <Route path="/signup" component={SignupPage} /> </div> </Router> </Provider> </ApolloProvider> ); } }
这是网络接口的创建:
const networkInterface = createNetworkInterface({ uri: process.env.NODE_ENV === 'development' ? 'http://localhost:3000/graphql' : 'TBD', }); networkInterface.use([ { applyMiddleware(req, next) { if (!req.options.headers) { req.options.headers = {}; // Create the header object if needed. } getUserSession() .then(session => { // get the authentication token from local storage if it exists // ID token! req.options.headers.authorization = session .getIdToken() .getJwtToken(); }) .catch(err => { console.error('oh, this is bad'); }) .then(next); }, }, ]);
我如何组织此内容,以便仅初始化Apollo客户端并设置一次,并且只有在用户身份验证?
之后我想知道我是否可以使用 withapollo 以某种方式访问客户直接并以这种方式完成GraphQl auth&Connection.
想法2
使用redux跟踪用户状态,用connect跟踪App.当用户进行身份验证时,这会触发触发App's componentDidUpdate的redux状态变化,该更改可能会创建Apollo的网络接口,从而在App中导致重新渲染,从而将授权client传递到
推荐答案
我通常会收听从redux设置为true的" isloggedin"字段.设置为true时,我渲染完整的应用程序并添加身份验证标头,以便该函数将JWT令牌添加到所有以后的请求中.
import React, { Component } from 'react'; import { ApolloProvider } from 'react-apollo'; import makeStore from '../../store'; import createClient from '../../ApolloClient'; class Sample extends Component { login() { // login logic here; } routeTo() { // use props or state; let isLoggedIn = this.props.isLoggedIn || this.state.loggedIn; if(isLoggedIn) { const client = createClient(myToken); const store = makeStore(myToken); return ( <ApolloProvider store={store} client={client} > <Routes screenProps={this.state} /> </ApolloProvider>); } else { return <LoginUI onPress={()=>this.login()}/>; } } render() { return( <div> {this.routeTo()} </div> ); }
其他推荐答案
我使用apolloclient示例 http://dev.apollodata.com/react/auth.html#标题
networkInterface.use([{ applyMiddleware(req, next) { if (!req.options.headers) { req.options.headers = {}; // Create the header object if needed. } // get the authentication token from local storage if it exists const token = localStorage.getItem('token'); req.options.headers.authorization = token ? `Bearer ${token}` : null; next(); } }])
块applyMiddleware将始终在获取GraphQl Server之前运行,因此您只需要在注销时登录和删除时设置localStorage.
其他推荐答案
const token = request.authToken; // localhost.get('authetoken) return { headers: { ...headers, Authorization: `Bearer ${token}`, }, }; });``` setContext will take care of that for you
问题描述
I'm a bit confused on how to structure my React/GraphQL (Apollo) app when no connection should be made until the user authenticates/logs in.
Currently I have this:
class App extends Component { render() { return ( <ApolloProvider client={client}> <Provider store={store}> <Router> <div> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/login">Log In</Link></li> <li><Link to="/signup">Sign Up</Link></li> </ul> <AuthenticatedRoute exact path="/" component={HomePage} /> <Route path="/login" component={LoginPage} /> <Route path="/signup" component={SignupPage} /> </div> </Router> </Provider> </ApolloProvider> ); } }
Here's the creation of the network interface:
const networkInterface = createNetworkInterface({ uri: process.env.NODE_ENV === 'development' ? 'http://localhost:3000/graphql' : 'TBD', }); networkInterface.use([ { applyMiddleware(req, next) { if (!req.options.headers) { req.options.headers = {}; // Create the header object if needed. } getUserSession() .then(session => { // get the authentication token from local storage if it exists // ID token! req.options.headers.authorization = session .getIdToken() .getJwtToken(); }) .catch(err => { console.error('oh, this is bad'); }) .then(next); }, }, ]);
How do I organize this so that the Apollo client is only initialized and set up once, and only after the user has authenticated?
I'm wondering if I could use withApollo to somehow access the client directly and complete the GraphQL auth & connection that way.
Idea 2
Use Redux to track user state, wrap App with connect. When the user authenticates, this triggers a Redux state change which triggers App's componentDidUpdate which could create the network interface for Apollo, causing a re-render in App which would pass an authorized client into <ApolloProvider client={client}>.
推荐答案
I typically listen for a "isLoggedIn" field to be set to true from redux. When it's set to true, I render the full app and add the authentication header so that the function adds the JWT token to all future requests.
import React, { Component } from 'react'; import { ApolloProvider } from 'react-apollo'; import makeStore from '../../store'; import createClient from '../../ApolloClient'; class Sample extends Component { login() { // login logic here; } routeTo() { // use props or state; let isLoggedIn = this.props.isLoggedIn || this.state.loggedIn; if(isLoggedIn) { const client = createClient(myToken); const store = makeStore(myToken); return ( <ApolloProvider store={store} client={client} > <Routes screenProps={this.state} /> </ApolloProvider>); } else { return <LoginUI onPress={()=>this.login()}/>; } } render() { return( <div> {this.routeTo()} </div> ); }
其他推荐答案
I use ApolloClient example http://dev.apollodata.com/react/auth.html#Header
networkInterface.use([{ applyMiddleware(req, next) { if (!req.options.headers) { req.options.headers = {}; // Create the header object if needed. } // get the authentication token from local storage if it exists const token = localStorage.getItem('token'); req.options.headers.authorization = token ? `Bearer ${token}` : null; next(); } }])
the block applyMiddleware will always run before fetching to GraphQL server, so you just need to set localStorage when login and delete when logout.
其他推荐答案
const token = request.authToken; // localhost.get('authetoken) return { headers: { ...headers, Authorization: `Bearer ${token}`, }, }; });``` setContext will take care of that for you