Как повторно отправлять запросы на сервер каждый раз, когда компонент вызывается в реакции-аполлоне и графике - PullRequest
0 голосов
/ 04 мая 2018

У меня есть этот проект, вроде как Facebook. Идея в том, что когда пользователь находится на странице своего профиля, он должен видеть список имен пользователей своих друзей. После нажатия на каждое имя пользователя приложение берет идентификатор этого человека из URL-адреса, а затем отправляет запрос graphql на сервер, чтобы получить все необходимые сведения об этом человеке. Ниже приведен метод, который вызывается, когда пользователь нажимает на имя пользователя любого друга. Это работает как ожидалось:

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

Затем в компоненте, который обрабатывает 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))

И запрос graphql:

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

Сначала, когда сайт загружается, я вижу список имен всех моих друзей и, нажимая на любого пользователя в первый раз, я получаю все необходимые данные. Однако, когда я возвращаюсь и нажимаю на другого пользователя, этот компонент профиля дает мне информацию о профиле первого пользователя, на которого я нажал. URL-адрес изменяется, чтобы отразить идентификатор этого нового пользователя, на которого щелкнули, но компонент не отображает правильные данные. Только когда я перезагружаю страницу, я получаю правильные данные. Делая некоторую отладку, я понимаю, что запрос к серверу даже не делается, когда я нажимаю на любое из этих имен пользователей, как во второй раз в палатах. Только когда я перезагружаю страницу, когда выполняется запрос. Мне нужна помощь чтобы узнать как пересылать запросы на сервер каждый раз, когда компонент вызывается в реакции-аполлоне и графике. (Я новичок в GraphQL)

1 Ответ

0 голосов
/ 04 мая 2018

В дополнение к запросу, graphql HOC принимает объект конфигурации в качестве второго параметра, который позволяет вам точно настроить поведение вашего запроса. Вы можете, например, определить fetchPolicy, который определяет, как Apollo использует кеш. По умолчанию, при получении того же запроса, Apollo впервые подключается к серверу, а затем использует кэш для последующих вызовов (это называется cache-first). Если вы хотите, чтобы ваш компонент всегда выполнял запрос при его монтировании, вы можете установить политику выборки на network-only:

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

Подробнее о правилах получения вы можете прочитать здесь .

Тем не менее, вам не нужно менять политику извлечения для достижения желаемого поведения. Частично проблема заключается в том, что вы фактически жестко программируете ввод id - вместо этого вы должны передавать любые динамические входные данные как переменные с каждым запросом. Это означает, что ваш запрос должен выглядеть примерно так:

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

Затем вы можете передать свою переменную следующим образом:

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

Примечание: похоже, что вы также используете React Router, поэтому вы должны иметь возможность получить идентификатор из match.params вместо того, чтобы анализировать местоположение самостоятельно. Подробнее здесь .

Наконец, важно понимать, что Apollo нормализует кэшируемые данные, и для этого он использует свойство id (или _id) данных. Поэтому, если вы хотите, чтобы поведение cache-first работало должным образом, вам нужно либо: а) убедиться, что вы всегда запрашиваете поле id в своих запросах, либо б) указать Apollo использовать другое поле, например id, настраивая InMemoryCache соответственно. Похоже, у вас уже есть поле идентификатора, поэтому достаточно просто изменить свой запрос, чтобы включить его:

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

Вы можете узнать больше о нормализации кэша и о том, как использовать dataIdFromObject для настройки поведения InMemoryCache по умолчанию здесь .

...