Javascript 从阿波罗商店检索数据
我创建了一个LoginMutation,它返回一个令牌和一个用户(带有他的id和名字)。 以下是突变模式:Javascript 从阿波罗商店检索数据,javascript,reactjs,apollo,react-apollo,apollo-client,Javascript,Reactjs,Apollo,React Apollo,Apollo Client,我创建了一个LoginMutation,它返回一个令牌和一个用户(带有他的id和名字)。 以下是突变模式: const LOGIN_MUTATION = gql` mutation loginMutation($email: String!, $password: String!) { loginUser(email: $email, password: $password) { token user { id firstNam
const LOGIN_MUTATION = gql`
mutation loginMutation($email: String!, $password: String!) {
loginUser(email: $email, password: $password) {
token
user {
id
firstName
}
}
}
当我进入我的网站时,graphql服务器会很好地返回令牌和用户。用户已存储,我可以在我的开发工具中看到它:
我已经创建了一个布局组件,我想在上面显示用户的名字。那么我怎样才能从阿波罗商店得到数据呢
谢谢你的帮助
以下是本期相关文件:
LoginPage.js
class LoginPage extends Component {
constructor(props) {
super(props);
this.state = {
login: true, //switch between Login and SignUp
email: '',
password: '',
firstName: '',
lastName: '',
loading: false,
error: ''
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleSubmit(){
this.setState({loading: true, error: ''});
this._confirm();
}
handleInputChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render(){
return (
<div>
<div>
{this.state.loading ?
<CircularProgress size={60} thickness={7} /> :
this.state.login ?
<LoginForm onSubmit={this.handleSubmit} onChange={this.handleInputChange}/>
:
<RegisterForm />
}
</div>
{this.state.error ? <div className="error">{this.state.error}</div> : ''}
<a
onClick={() => this.setState({ login: !this.state.login })}
>
{this.state.loading ?
'' : this.state.login ?
'Besoin d\'un compte ?' : 'Déjà un compte ?'
}
</a>
</div>
)
}
_confirm = () => {
const { firstName, lastName, email, password } = this.state;
if (this.state.login) {
this.props.loginMutation({
variables: {
email,
password,
}
})
.then(({data}) => {
this.setState({loading: false});
const { token } = data.loginUser;
this._saveUserData(token);
checkAuth.authenticate();
})
.then(() => {
this.props.history.push(`/`);
}).catch((error) => {
this.setState({loading: false, error: error});
});
}
}
_saveUserData = (token) => {
localStorage.setItem('token', token);
}
}
const LOGIN_MUTATION = gql`
mutation loginMutation($email: String!, $password: String!) {
loginUser(email: $email, password: $password) {
token
user {
id
firstName
}
}
}
`
export default compose(graphql(LOGIN_MUTATION, { name: 'loginMutation' }))(LoginPage)
class WelcomePage extends Component {
render() {
return (
<div>
<Layout>
<WelcomeComponent />
</Layout>
</div>
);
}
}
export default WelcomePage;
类登录页扩展组件{
建造师(道具){
超级(道具);
此.state={
login:true,//在登录和注册之间切换
电子邮件:“”,
密码:“”,
名字:'',
姓氏:“”,
加载:false,
错误:“”
};
this.handleSubmit=this.handleSubmit.bind(this);
this.handleInputChange=this.handleInputChange.bind(this);
}
handleSubmit(){
this.setState({loading:true,错误:“”});
这个;
}
handleInputChange(事件){
const target=event.target;
常量值=target.value;
const name=target.name;
这是我的国家({
[名称]:值
});
}
render(){
返回(
{this.state.loading?
:
这个是.state.login吗?
:
}
{this.state.error?{this.state.error}:''
this.setState({login:!this.state.login})
>
{this.state.loading?
'':这个.state.login?
“你说什么?”
}
)
}
_确认=()=>{
const{firstName,lastName,email,password}=this.state;
if(this.state.login){
this.props.loginMutation({
变量:{
电子邮件,
密码,
}
})
。然后({data})=>{
this.setState({loading:false});
const{token}=data.login用户;
此._saveUserData(令牌);
checkAuth.authenticate();
})
.然后(()=>{
this.props.history.push(`/`);
}).catch((错误)=>{
this.setState({loading:false,error:error});
});
}
}
_saveUserData=(令牌)=>{
setItem('token',token);
}
}
const LOGIN_MUTATION=gql`
变异登录变异($email:String!,$password:String!){
登录用户(电子邮件:$email,密码:$password){
代币
使用者{
身份证件
名字
}
}
}
`
导出默认组合(graphql(LOGIN_MUTATION,{name:'loginMutation'}))(LoginPage)
App.js这是页面之间的路由器
class App extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Switch>
<Route exact path='/connexion' component={LoginPage} />
<PrivateRoute exact path='/' component={WelcomePage} />
</Switch>
</div>
)
}
}
export default App;
类应用程序扩展组件{
建造师(道具){
超级(道具);
}
render(){
返回(
)
}
}
导出默认应用程序;
Layout.js我想从缓存中获取用户名,并将其传递到边栏道具上
class Layout extends Component {
constructor(props) {
super(props);
this.state = {
open: false,
};
this.logout = this.logout.bind(this);
}
logout() {
this.props.client.resetStore();
localStorage.removeItem('token');
checkAuth.signout();
this.props.history.push(`/`);
}
handleTouchMap() {
this.setState({open: !this.state.open});
}
render() {
return (
<div>
<AppBar title="myApp" iconElementRight={<RightMenu onDisconnect={ this.logout } />} onLeftIconButtonTouchTap = { this.handleTouchMap.bind(this) } />
<Sidebar open={this.state.open} onRequestChange={(open) => this.setState({open})} firstName={this.props.firstName} />
{ this.props.children }
</div>
);
}
}
export default withApollo(withRouter(Layout));
类布局扩展组件{
建造师(道具){
超级(道具);
此.state={
开:错,
};
this.logout=this.logout.bind(this);
}
注销(){
this.props.client.resetStore();
localStorage.removietem('token');
checkAuth.signout();
this.props.history.push(`/`);
}
handleTouchMap(){
this.setState({open:!this.state.open});
}
render(){
返回(
this.setState({open}}firstName={this.props.firstName}/>
{this.props.children}
);
}
}
使用Apollo导出默认值(使用路由器(布局));
WelcomePage.js
class LoginPage extends Component {
constructor(props) {
super(props);
this.state = {
login: true, //switch between Login and SignUp
email: '',
password: '',
firstName: '',
lastName: '',
loading: false,
error: ''
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleSubmit(){
this.setState({loading: true, error: ''});
this._confirm();
}
handleInputChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render(){
return (
<div>
<div>
{this.state.loading ?
<CircularProgress size={60} thickness={7} /> :
this.state.login ?
<LoginForm onSubmit={this.handleSubmit} onChange={this.handleInputChange}/>
:
<RegisterForm />
}
</div>
{this.state.error ? <div className="error">{this.state.error}</div> : ''}
<a
onClick={() => this.setState({ login: !this.state.login })}
>
{this.state.loading ?
'' : this.state.login ?
'Besoin d\'un compte ?' : 'Déjà un compte ?'
}
</a>
</div>
)
}
_confirm = () => {
const { firstName, lastName, email, password } = this.state;
if (this.state.login) {
this.props.loginMutation({
variables: {
email,
password,
}
})
.then(({data}) => {
this.setState({loading: false});
const { token } = data.loginUser;
this._saveUserData(token);
checkAuth.authenticate();
})
.then(() => {
this.props.history.push(`/`);
}).catch((error) => {
this.setState({loading: false, error: error});
});
}
}
_saveUserData = (token) => {
localStorage.setItem('token', token);
}
}
const LOGIN_MUTATION = gql`
mutation loginMutation($email: String!, $password: String!) {
loginUser(email: $email, password: $password) {
token
user {
id
firstName
}
}
}
`
export default compose(graphql(LOGIN_MUTATION, { name: 'loginMutation' }))(LoginPage)
class WelcomePage extends Component {
render() {
return (
<div>
<Layout>
<WelcomeComponent />
</Layout>
</div>
);
}
}
export default WelcomePage;
class WelcomePage扩展组件{
render(){
返回(
);
}
}
导出默认页面;
有两个选项。首先,我将解释我喜欢的解决方案,它非常简单,然后是更简单的解决方案
首先,实现一个基本查询
在您的情况下,它将类似于:
const CURRENT_USER_QUERY = gql`
query currentUserQuery {
user {
id
firstName
}
}`;
graphql(LOGIN_MUTATION, { name: 'loginMutation',
update: (proxy, { data: { loginUser } }) => {
const data = { user: loginUser.user };
proxy.writeQuery({ query: CURRENT_USER_QUERY, data });
}
})
您可以这样将其添加到布局
组件中:
export default compose(
withApollo,
graphql(CURRENT_USER_QUERY, { /* ... query configuration */ })
)(withRouter(Layout));
请注意,其中一个查询选项是fetchPolicy
。在此特定场景中,您可能只需要缓存
。一开始就足够了,但是当您添加更多的字段时,您可能需要考虑将其更改为更适合您的设计。在这里你可以读到
现在这个查询仍然无法检索数据,因为它没有按照查询的预期存储。这就引出了第二部分:
其次,在变异后更新缓存
为此,您需要在变异操作中使用update
选项
在您的情况下,突变操作应该如下所示:
const CURRENT_USER_QUERY = gql`
query currentUserQuery {
user {
id
firstName
}
}`;
graphql(LOGIN_MUTATION, { name: 'loginMutation',
update: (proxy, { data: { loginUser } }) => {
const data = { user: loginUser.user };
proxy.writeQuery({ query: CURRENT_USER_QUERY, data });
}
})
如果您看过文档中的示例,您可以看到此处没有调用proxy.readQuery
,原因有二
- 在这种登录情况下,可以安全地假设
为用户
。这可能与其他突变无关null
- 如果您试图读取的对象不在缓存中,
将引发异常proxy.readQuery
const USER_QUERY = gql`
query userQuery($userId: ID) {
user(id: $userId) {
id
firstName
}
}`;
// ...
export default compose(
withApollo,
graphql(USER_QUERY, {
variables: () => {
return { userId: /* get the user id, maybe from the local storage*/};
},
/* ... query configuration */
}),
)(withRouter(Layout));
正如您所看到的,回退是您始终需要存储并提供用户id以获取当前用户的数据。当你发现你需要在其他地方访问用户的数据时,这可能会很麻烦。你会在这个链接上看到清晰的图片谢谢你的回复javed,我已经读过了,其中一句话非常有趣