#reactjs #graphql #relay #relaymodern #react-relay
Вопрос:
Используя react 17 и relay-modern 11, я хочу создать список, с помощью которого, когда кто-то дойдет до конца, они могут нажать кнопку с надписью «Загрузить больше», и она добавит больше записей в список. Вот что у меня есть на данный момент. Строки-это имя и курсор
смотрите, я должен нажать «Загрузить больше», и он должен добавить дополнительные 5 строк данных. Вот что происходит, когда я нажимаю загрузить больше
Смотрите, он получил 5 новых узлов. Я могу сказать это, потому что курсоры уникальны. Однако он не добавил его в список, как я хотел.
Как я могу заставить этот список продолжать создаваться все время, пока я продолжаю нажимать «Загрузить больше», пока больше не останется данных?
Вот мой код:
корень компонента:
// index.js
import React, { useState } from "react";
import { Text, View } from "react-native";
import { QueryRenderer, useRelayEnvironment } from "react-relay";
import PaginatedProfilesListContainer from "./PaginatedProfilesListContainer";
const ProfilesList = () => {
const environment = useRelayEnvironment();
const [count, setCount] = useState(5);
const [name, setName] = useState("");
const query = graphql`
query ProfilesListQuery(
$count: Int!
$cursor: String
$filter: ProfileFilter
) {
...PaginatedProfilesListContainer_list
}
`;
const filter = {
name,
};
const variables = {
count: 5,
cursor: null,
filter,
};
const render = ({ error, props, retry }) => {
if (error) {
return (
<View>
<Text>{error.message}</Text>
</View>
);
} else if (props) {
return (
<View>
<PaginatedProfilesListContainer
pagination={props}
count={count}
setCount={setCount}
name={name}
setName={setName}
filter={filter}
/>
</View>
);
} else {
return (
<View>
<Text>loading profiles list...</Text>
</View>
);
}
};
console.log("vriable", variables)
return (
<QueryRenderer
environment={environment}
query={query}
variables={variables}
render={render}
/>
);
};
export default ProfilesList;
вот компонент, в котором должен быть указан объект
// PaginatedProfilesListContainer.js
import React from "react";
import { Text, View } from "react-native";
import { Button } from "react-native-paper";
import { createPaginationContainer } from "react-relay";
import { FadoTextInput } from "../forms/fadoTextInput";
const PaginatedProfilesListContainer = (props) => {
console.log(props);
console.log("createPaginationContainer", createPaginationContainer)
// console.log(pagination)
const { pagination, count, setCount, name, setName, relay, filter } = props;
const { hasMore, loadMore, refetchConnection } = relay;
console.log(loadMore)
const { profiles } = pagination;
const { edges, pageInfo } = profiles;
return (
<View>
<View>
<FadoTextInput
dense={true}
isNumeric={true}
graphqlErrors={[]}
label="count"
errorKey="count"
// savedValue={price.amount}
value={count}
onChangeText={setCount}
/>
<FadoTextInput
dense={true}
isNumeric={false}
graphqlErrors={[]}
label="name"
errorKey="name"
// savedValue={price.amount}
value={name}
onChangeText={setName}
/>
</View>
{edges.map(({ cursor, node: { name } }) => (
<View key={cursor} style={{ display: "flex", flexDirection: "row"}}>
<Text>{name}</Text>
<Text>{cursor}</Text>
</View>
))}
<Button disabled={!hasMore()} onPress={() => loadMore(count, (error) => { error amp;amp; console.log("error", error); })}>
Load More
</Button>
</View>
);
};
export default createPaginationContainer(
PaginatedProfilesListContainer,
{
pagination: graphql`
fragment PaginatedProfilesListContainer_list on RootQueryType {
profiles(first: $count, after: $cursor, filter: $filter)
@connection(key: "PaginatedProfilesListContainer_profiles") {
pageInfo {
endCursor
hasNextPage
hasPreviousPage
startCursor
}
edges {
cursor
node {
name
}
}
}
}
`,
},
{
direction: 'forward',
query: graphql`
query PaginatedProfilesListContainerQuery(
$count: Int!
$cursor: String
$filter: ProfileFilter
) {
...PaginatedProfilesListContainer_list
}
`,
getConnectionFromProps(props) {
console.log(props)
return props.pagination?.profiles
},
getFragmentVariables(prevVars, totalCount) {
return {
...prevVars,
count: totalCount,
};
},
getVariables(props, { count, cursor }, fragmentVariables) {
return {
count,
cursor,
filter: {},
};
},
}
);
Я получил вдохновение для этого подхода от https://github.com/facebook/relay/issues/1705
Примечание: Я пытался использовать @stream_connection, но абсент Эликсира на бэкэнде, похоже, не поддерживает его.
Я знаю, что это долго, поэтому, пожалуйста, любая помощь будет оценена по достоинству 🙂
Комментарии:
1. Вы уверены
return props.pagination?.profiles
, что вgetConnectionFromProps
методе это не должно быть чем-то подобнымreturn props.profiles
? Потому что у меня точно такие же запросы, как у вас, но разница только в этой строке.2. И чтобы исправить все проблемы с разбиением на страницы с помощью реле, я использую эти крючки для использования из пакета крючков реле.
4. чтобы отключить функцию loadMore от usePagination, я создал такую функцию:
const handleScrollForPagination = (e: any) => { if ( e.target.scrollTop > 0 amp;amp; Math.ceil(e.target.scrollTop e.target.clientHeight) >= e.target.scrollHeight ) { loadMore(); } };
поэтому, когда вы находитесь в нижней части полосы прокрутки, вызывается метод loadMore (). И я добавляю его вonScroll
реквизит контейнера для разбиения на страницы5. огромное спасибо. Я наконец-то заставил его работать…. эта ссылка также помогла всем, кто исследует это github.com/facebook/relay/issues/2938#issuecomment-552888060