ast*_*ije 16 javascript apollo reactjs react-apollo apollo-client
我们目前正在从Relay转向React Apollo 2.1,而我正在做的事似乎很可疑.
上下文:只有在用户通过身份验证(通过API密钥)时才能呈现某些组件,因此有一个Authenticator组件可以保护树的其余部分.
在App.js,它被这样使用(显然下面的所有片段都是最小的例子):
import React from 'react';
import Authenticator from './Authenticator';
import MyComponent from './MyComponent';
export default function App({ apiKey }) {
return (
<Authenticator apiKey={apiKey}
render={({ error, token }) => {
if (error) return <div>{error.message}</div>;
if (token) return <MyComponent token={token} />;
return <div>Authenticating...</div>;
}}
/>
);
}
Run Code Online (Sandbox Code Playgroud)
如果身份验证成功,MyComponent则会进行呈现.
Authentication在第一次渲染/挂载时将身份验证突变发送到服务器,并相应地调用渲染道具.
Authentication.js看起来像这样:
import gql from 'graphql-tag';
import React from 'react';
import { Mutation } from 'react-apollo';
const AUTH_MUTATION = gql`mutation Login($apiKey: String!) {
login(apiKey: $apiKey) {
token
}
}`;
export default function Authenticator({ apiKey, render }) {
return (
<Mutation mutation={AUTH_MUTATION} variables={{ apiKey }}>
{(login, { data, error, called }) => {
if (!called) login(); // ?? This seems sketchy ??
const token = (data && data.login.token) || undefined;
return render({ error, token });
}}
</Mutation>
);
}
Run Code Online (Sandbox Code Playgroud)
这if (!called) login();就是让我暂停的原因.如果我没有指定if (!called),UI会变得癫痫并发送数千个请求(这是有道理的,调用login()原因render()重新运行),但是应该如何使用它?
似乎Query组件等效的不同之处在于简单地渲染它会发出请求.我想知道是否有办法应用相同的机制Mutation,这需要调用mutate函数作为渲染道具的一部分.
上面代码段的Relay相当于React Apollo Query所做的事情Mutation:
// Authentication.js
import React from 'react';
import { graphql, QueryRenderer } from 'react-relay';
import { Environment } from 'relay-runtime';
// Hiding out all the `Environment`-related boilerplate
const environment = return new Environment(/* ... */);
const AUTH_MUTATION = graphql`mutation Login($apiKey: String!) {
login(apiKey: $apiKey) {
token
}
}`;
export default function Authenticator({ apiKey, render }) {
return (
<QueryRenderer query={AUTH_MUTATION} variables={{ apiKey }}
render={render}
/>
);
}
// App.js
import React from 'react';
import Authenticator from './Authenticator';
import MyComponent from './MyComponent';
export default function App({ apiKey }) {
return (
<Authenticator apiKey={apiKey}
render={({ error, props }) => {
if (error) return <div>{error.message}</div>;
if (props) return <MyComponent token={props.loginAPI.token)} />;
return <div>Authenticating...</div>;
}}
/>
);
}
Run Code Online (Sandbox Code Playgroud)
Dan*_*den 18
对或错,Apollo对如何使用查询和突变做出一些假设.按照惯例,查询只会在突变时获取数据,好吧,变异数据.阿波罗进一步采用这种模式,并假设突变将在某种行动中发生.因此,就像你观察到的那样,Query在mount上获取查询,同时Mutation传递一个函数来实际获取变异.
从这个意义上说,你已经偏离了"应该使用这些组件"的方式.
我不认为你的方法有任何直接的错误 - 假设called永远不会重置,你的组件应该按预期运行.但是,作为替代方案,您可以创建一个简单的包装器组件来利用componentDidMount:
class CallLogin extends React.Component {
componentDidMount() {
this.props.login()
}
render() {
// React 16
return this.props.children
// Old School :)
// return <div>{ this.props.children }</div>
}
}
export default function Authenticator({ apiKey, render }) {
return (
<Mutation mutation={AUTH_MUTATION} variables={{ apiKey }}>
{(login, { data, error }) => {
const token = (data && data.login.token) || undefined;
return (
<CallLogin login={login}>
{render({ error, token })}
</CallLogin>
)
}}
</Mutation>
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4553 次 |
| 最近记录: |