Closed cliedeman closed 3 years ago
Hi @cliedeman, I did not understand the problem well.
When you invoke the Retry, the dispose of the previous request is performed and the previous error value is reset: https://github.com/relay-tools/relay-hooks/blob/master/src/QueryFetcher.ts#L113
Following the new fetch they will be updated based on its success or failure.
Hi @morrys , let me try again
Sample Error Component
interface Props {
error: Error;
retry?(): void;
}
export function Error({error, retry}: Props) {
return (
<div>
{error.message}
{retry && <Button onClick={retry}>Retry</Button>}
</div>
);
}
I will try to explain what happens based on the props
# 1st Render
{props: null, error: null} => Render Loading Component
# 2nd Render:Server unreachable
{props: null, error: SomeError} => Render Error Component
# 3rd User Clicks retry button
{props: null: error: SomeError => Render Error Component
# 4th Render, call succeeds
{props: User, error: null} => Render data
After the user clicks the error button I expect the error to be cleared or alternatively some way to detect that a retry is being executed
An Alternative solution I just thought up
const AppTodo = function (appProps) {
const {props, error, retry, cached, isRetrying} = useQuery(query, variables, options);
if (props && props.user) {
return <TodoApp user={props.user} />;
} else if (isRetrying) {
return <div>loading</div>;
} else if (error) {
return <Error error={error} retry={retry}/>;
}
return <div>loading</div>;
}
Ciaran
Try this sample project without starting the server and editing the app.js file with this:
import * as React from 'react';
import { useQuery, RelayEnvironmentProvider } from 'relay-hooks';
import { Environment, Network, RecordSource, Store } from 'relay-runtime';
import { create } from './mutations/create';
import QueryApp from './query/QueryApp';
import Entries from './components/Entries';
async function fetchQuery(operation, variables) {
const response = await fetch('http://localhost:3003/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: operation.text,
variables,
}),
});
return response.json();
}
const modernEnvironment = new Environment({
network: Network.create(fetchQuery),
store: new Store(new RecordSource()),
});
const AppTodo = (propsApp) => {
const [, forceUpdate] = React.useReducer(x => x + 1, 0);
const { props, error, retry } = useQuery(
QueryApp,
{},
{
fetchPolicy: 'store-or-network',
},
); /*propsApp; */
async function submitEntry() {
await create('try', modernEnvironment).catch(console.error);
}
console.log("renderer", error)
if (props && props.entries) {
return (
<React.Fragment>
<button onClick={submitEntry} className="refetch">
Add
</button>
<Entries entries={props.entries} />
</React.Fragment>
);
} else if (error) {
return <button onClick={() => {retry(); forceUpdate();}} className="refetch">
Retry
</button>;
}
return <div>loading</div>;
};
const App = (
<RelayEnvironmentProvider environment={modernEnvironment}>
<AppTodo />
</RelayEnvironmentProvider>
);
export default App;
@cliedeman Did you find any solution for this problem? I have the same issue.
in version 3.x it is necessary to perform the forceUpdate as described in this comment https://github.com/relay-tools/relay-hooks/issues/129#issuecomment-737316301
While in version 4.x it is managed natively
@morrys Thanks, I can confirm this is working as expected in version 4.0.0
A pattern I use quite often is simliar to the example
But on failure if I invoke retry the error is not reset and the loading section is displayed
Ciaran