Несколько маршрутов реакции-маршрутизатора-ретранслятора с использованием одного корневого запроса ретрансляции с различными полями фрагмента
Я сталкиваюсь с проблемой, когда при запросе данных в двух смежных компонентах маршрута relay-router-relay, использующих тот же корневой запрос, запрос сервера graphql во втором компоненте маршрута делает недействительными данные, ранее полученные из первого.
В качестве примера:
Я использую обходной путь для присоединения полей к корневому узлу "просмотра", чтобы запросить массивы данных из корневого поля:
Мой schema.js содержит следующие определения для типа просмотра (пользователя) и корня:
var GraphQLUser = new GraphQLObjectType({
name: 'User',
isTypeOf: function(obj) { return obj instanceof User },
fields: function() {
return {
id: GraphQLRelay.globalIdField('User'),
//Fields to expose to app, e.g. cars
cars: {
type: GraphQLRelay.connectionDefinitions({
name: 'Car', nodeType: carType
}).connectionType,
args: GraphQLRelay.connectionArgs,
resolve: function(user, args) {
return
GraphQLRelay.connectionFromPromisedArray(getCars(), args)
},
},
}
},
interfaces: [nodeDefinitions.nodeInterface],
});
И корень:
var Root = new GraphQLObjectType({
name: 'Root',
fields: {
viewer: {
type: GraphQLUser,
resolve: (root, {} ) => getUser()
},
node: nodeDefinitions.nodeField
});
Теперь в точке входа приложения main.jsx я определяю следующие маршруты:
ReactDOM.render(
<Router createElement={ReactRouterRelay.createElement}>
<Route path="/" component={App} queries={ViewerQueries} />
<Route path="/cars" component={AllCars} queries={ViewerQueries} />
</Router>,
document.getElementById('ReactContainer'));
с ViewerQueries.js, содержащим:
export default {
viewer: () => Relay.QL`query { viewer }`,
};
Теперь, если App
Компонент включает следующий фрагмент graphql:
exports.Component = Relay.createContainer(App, {
initialVariables: {
limit: 10
},
fragments: {
viewer: () => Relay.QL`
fragment on User {
cars (first: $limit) {
edges {
node {
name,
}
}
}
}`,
},
})
И AllCars
Компонент включает в себя следующее:
exports.Component = Relay.createContainer(AllCars, {
initialVariables: {limit: 10},
fragments: {
viewer: () => Relay.QL`
fragment on User {
cars (first: $limit) {
edges {
node {
name,
type
}
}
}
}`,
},
})
получается, что при рендеринге компонента App по пути '/' массив машин возвращается без проблем. Тем не менее, после отображения пути "/cars", результирующий массив в this.props.viewer.cars становится пустым. Кроме того, возврат к пути '/' для повторного рендеринга компонента App теперь также возвращает пустой массив.
На бэкэнде, похоже, компонент AllCars вызывает дополнительный POST /graphql 200 277.369 ms - 94
поездка на сервер за новым type
указано во фрагменте. Если компонент AllCars содержит только поле "имя", Relay правильно не выполняет другой запрос к серверу, а вместо этого заполняет массив данными (предположительно, кешируется из первоначального запроса к серверу компонента App).
Разве нельзя получить массив автомобилей из любого компонента, когда Relay получит какие-либо дополнительные поля данных, указанные во фрагментах, независимо от их порядка на маршрутах?
Любая помощь будет принята с благодарностью!
2 ответа
Проблема оказалась недействительной nodedefinitions
для (пример) Car
введите в schema.js
файл. Определения узлов, которые я в итоге использовал:
var nodeDefinitions = GraphQLRelay.nodeDefinitions(function(globalId) {
var idInfo = GraphQLRelay.fromGlobalId(globalId)
if (idInfo.type == 'Car') {
return getCarById(idInfo.id)
} else if ...
// Other types here
}
return null
});
Возвращенная функция getCarById не правильно разрешила объект Car, и сервер GraphQL не смог получить дополнительные точки данных, запрошенные Relay, в результате чего вместо этого было возвращено нулевое значение, что фактически сводило на нет ранее выбранные объекты. Car
Предметы.
Кроме того, определение Root недопустимо и должно быть:
var Root = new GraphQLObjectType({
name: 'Root',
fields: {
viewer: {
type: GraphQLUser,
resolve: (root, {} ) => getUser()
},
node: nodeDefinitions.nodeField
}
});
Неуместный node
из-за определения поля сервер GraphQL пожаловался на невозможность запросить поле "узел" в корневом запросе.
После этих исправлений Relay может запрашивать одно и то же корневое поле, используя разные точки данных, независимо от размещения в <Route/>
дерево.
Хотя вложенные маршруты, вероятно, предпочтительнее для основных / подробных списков одного и того же типа объекта, иногда желательно включать одни и те же данные в несвязанные компоненты React (например, боковые панели, заголовки и т. Д.)
(Отправка как ответ, потому что я не могу отформатировать код в комментарии.)
Описанный вами сценарий хорошо подходит для использования вложенных маршрутов:
ReactDOM.render(
<Router createElement={ReactRouterRelay.createElement}>
<Route path="/" component={App} queries={ViewerQueries}>
<Route path="/cars" component={AllCars} queries={ViewerQueries} />
</Route>
</Router>,
document.getElementById('ReactContainer')
);
Если вы все еще видите пустые массивы с этой структурой, можете ли вы предоставить ссылку на список, содержащий запросы и ответы, отправленные по сети?