简体   繁体   English

每次在react-apollo和graphql中调用组件时如何将查询重新发送到服务器

[英]How to resend queries to server every time a component is called in react-apollo and graphql

I have this project, kinda like Facebook. 我有这个项目,有点像Facebook。 The idea is, when a user is in their profile page, they should see a list of their friends' usernames. 这个想法是,当用户在其个人资料页面中时,他们应该看到朋友的用户名列表。 Upon clicking on each username, the app is taking the id of that person from the url, then sending a graphql query to the server, to fetch all relevant details of that person. 单击每个用户名后,应用程序将从URL中获取该人的ID,然后将graphql查询发送到服务器,以获取该人的所有相关详细信息。 Below is the method that gets called when a user clicks on the username of any friend. 下面是当用户单击任何朋友的用户名时调用的方法。 This works as expected: 这按预期工作:

onClickFriend(e) {
    e.preventDefault()
    this.props.history.push(`/friends/${ e.target.id}`)
}

Then in the component that handles the url visited by the user (ie the component to show friends profile) contains the following code: 然后,在处理用户访问的url的组件(即显示好友配置文件的组件)中包含以下代码:

import React from 'react'
import PostsColumn from "./posts/PostsColumn"
import NewPostForm from "./posts/NewPostForm"
import {fetchFriendProfile} from "../queries/queries"
import {graphql} from 'react-apollo'
import {withRouter } from 'react-router'

const FriendProfile=({data})=>{
    const {loading, error, fetchFriendProfile} = data
    if (loading) return <p>Loading...</p>
    if (error) return <p>{error}(</p>

    const {username, birthday, profile_picture} = fetchFriendProfile
    return (
        <div className="row">
            <div className="col-sm-3">
                <br/>

                <img src={`/uploads/${profile_picture}`} alt="Profile picture" width="200" height="200"/>
                <ul>
                    <li>{username}</li>
                    <li>{new Date(birthday).toDateString()}</li>
                </ul>
            </div>
            <div className="col-sm-6">
                <br/>
                <br/>
                <div className="content-feed">
                    <NewPostForm/>
                </div>

                {/*<PostsColumn />*/}
            </div>


        </div>
    )
}
export default graphql(fetchFriendProfile)(withRouter(FriendProfile))

And the graphql query is: 而graphql查询是:

import {gql} from 'apollo-boost'
const fetchPalPosts = gql`
  {
 fetchFriendPosts(id:"${window.location.pathname.split('/')[2]}") {
    username
    birthday
    profile_picture
    }
    }
    `
export { fetchFriendProfile}

At first when the site loads, I see the list of usernames of all my friends, and clicking on any user the first time, I get all the relevant details. 最初,当网站加载时,我会看到所有朋友的用户名列表,并且在第一次单击任何用户时,都会得到所有相关详细信息。 However, when I go back and click on another user, this profile component gives me the profile details of the first user I clicked. 但是,当我返回并单击另一个用户时,此配置文件组件为我提供了我单击的第一个用户的配置文件详细信息。 The url is changing to reflect the id of this new clicked person, but the component does not display the correct details. url更改为反映此新单击的人员的id,但是该组件未显示正确的详细信息。 Only when I reload the page that I get the correct details. 只有重新加载页面后,我才能获得正确的详细信息。 Doing some debugging I realize that a query to the server is not even being made when I click any of these usernames as from the second time on wards. 通过进行一些调试,我意识到从第二次开始,单击这些用户名中的任何一个,甚至都不会查询服务器。 Only when I reload the page is when the query is being made. 只有当我重新加载页面时,才进行查询。 I need help to know how to resend queries to server every time a component is called in react-apollo and graphql. 我需要帮助,以了解每次在react-apollo和graphql中调用组件时如何将查询重新发送到服务器。 (Am a beginner to graphql) (是graphql的初学者)

In addition to the query, the graphql HOC accepts a configuration object as its second parameter that allows you to fine-tune how your query behaves. 除了查询之外, graphql HOC graphql配置对象作为其第二个参数,使您可以微调查询的行为。 You can, for example, define the fetchPolicy which determines how Apollo uses the cache. 例如,您可以定义fetchPolicy来确定Apollo如何使用缓存。 By default, when fetching the same query, Apollo will hit the server the first time and then use the cache for subsequent calls (this is called cache-first ). 默认情况下,在获取相同查询时,Apollo将首次访问服务器,然后将缓存用于后续调用(这称为cache-first )。 If you want your component to always hit the request when it mounts, you can set the fetch policy to network-only : 如果您希望组件在挂载时始终点击请求,则可以将提取策略设置为network-only

export default graphql(fetchFriendProfile, {
  options: (props) => ({
    fetchPolicy: 'network-only',
  }),
})(withRouter(FriendProfile))

You can read more about fetch policies here . 您可以在此处阅读有关获取策略的更多信息。

That said, you don't need to change the fetch policy to achieve your desired behavior. 也就是说,您无需更改获取策略即可实现所需的行为。 Part of the problem is that you're effectively hardcoding the id input -- instead, you should be passing in any dynamic inputs as variables with each query. 问题的一部分是您正在有效地对id输入进行硬编码-相反,您应该在每个查询中将任何动态输入作为变量传递。 That means your query needs to look something like this: 这意味着您的查询需要看起来像这样:

# Note: the actual type for $id will have to match your schema!
query WhateverNameYouLike ($id: ID!){ 
  fetchFriendPosts(id: $id) {
    username
    birthday
    profile_picture
  }
}

Then you can pass in your variable like this: 然后,您可以像这样传递变量:

export default graphql(fetchFriendProfile, {
  options: (props) => ({
    variables: {
      id: window.location.pathname.split('/')[2],
    },
  }),
})(withRouter(FriendProfile))

Side note: it looks like you're also using React Router, so you should be able to grab the id from match.params instead of parsing the location yourself. 旁注:看起来您也正在使用React Router,因此您应该能够从match.params获取ID,而不是自己解析位置。 Read more here . 在这里阅读更多。

Lastly, it's important to realize that Apollo normalizes the data it caches -- and it relies on the data's id (or _id ) property to do so. 最后,重要的是要认识到Apollo会规范化其缓存的数据-并且它依赖于数据的id (或_id )属性来实现。 So if you want the cache-first behavior to work as expected, you need to either a) make sure you always request the id field in your queries, or b) tell Apollo to use a different field as the id by configuring InMemoryCache accordingly. 因此,如果您希望cache-first行为按预期工作,则需要a)确保始终在查询中请求id字段,或者b)通过相应地配置InMemoryCache来告诉Apollo使用其他字段作为id It sounds like you already have an id field, so it's simple enough to modify your query to include it: 听起来您已经有一个id字段,所以修改查询以包含它就足够简单了:

query WhateverNameYouLike ($id: ID!){ 
  fetchFriendPosts(id: $id) {
    id
    username
    birthday
    profile_picture
  }
}

You can read more about cache normalization and how to use dataIdFromObject to customize InMemoryCache's default behavior here . 您可以在此处阅读有关缓存规范化以及如何使用dataIdFromObject自定义InMemoryCache的默认行为的更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM