Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/444.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从阿波罗商店检索数据_Javascript_Reactjs_Apollo_React Apollo_Apollo Client - Fatal编程技术网

Javascript 从阿波罗商店检索数据

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

我创建了一个LoginMutation,它返回一个令牌和一个用户(带有他的id和名字)。 以下是突变模式:

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,我已经读过了,其中一句话非常有趣