簡體   English   中英

從 Apollo 存儲中檢索數據

[英]Retrieve data from Apollo store

我創建了一個 LoginMutation,它返回一個令牌和一個用戶(帶有他的 id 和 firstName)。 這是突變模式:

const LOGIN_MUTATION = gql`
  mutation loginMutation($email: String!, $password: String!) {
    loginUser(email: $email, password: $password) {
      token
      user {
        id
        firstName
      }
    }
  }

當我在我的網站上輸入令牌和用戶時,graphql 服務器會很好地返回。 用戶已存儲,我可以在我的開發工具中看到它:

在此處輸入圖片說明

我創建了一個布局組件,我想在它上面顯示用戶的名字。 那么如何從 apollo 商店獲取數據呢?

感謝您的幫助。

下面提供了與此問題有關的文件:

登錄頁面.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)

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;

Layout.js ,我想從緩存中獲取用戶 firstName 以將其傳遞給側邊欄道具

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));

歡迎頁面.js

class WelcomePage extends Component {
    render() {
        return (
            <div>
                <Layout>
                    <WelcomeComponent />
                </Layout>
            </div>
        );
    }
}

export default WelcomePage;

有2個選項。 首先,我將解釋我喜歡的非常簡單的解決方案,然后是更簡單的解決方案。

首先,實現一個基本查詢

在你的情況下,它會是這樣的:

const CURRENT_USER_QUERY = gql`
  query currentUserQuery {  
    user {
        id
        firstName
      }
   }`;

您可以像這樣將它添加到Layout組件中:

export default compose(
  withApollo,
  graphql(CURRENT_USER_QUERY, { /* ... query configuration */ })
)(withRouter(Layout));

請注意,查詢選項之一是fetchPolicy 在這個特定場景中,您可能只需要cache-only 剛開始應該足夠了,但是隨着您添加更多字段,您可能需要考慮將其更改為更適合您的設計的內容。 在這里您可以閱讀有關查詢獲取策略的信息

現在這個查詢仍然不會檢索數據,因為它沒有按照查詢的預期存儲。 這就引出了第二部分:

二、突變后更新緩存

為此,您需要在變異操作中使用update選項。

在您的情況下,變異操作應該類似於:

graphql(LOGIN_MUTATION, { name: 'loginMutation',
  update: (proxy, { data: { loginUser } }) => {      
    const data = { user: loginUser.user };
    proxy.writeQuery({ query: CURRENT_USER_QUERY, data });
  }
})

如果你看過文檔中的例子,你會發現這里沒有調用proxy.readQuery ,原因有二。

  • 在這種登錄情況下,假設usernull是安全的。 它可能與其他突變無關。
  • 如果您嘗試讀取的對象不在緩存中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來獲得當前用戶的數據。 當您發現需要訪問其他地方的用戶數據時,這可能會很麻煩。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM