κ·Έλμ μ λ Apollo-link-errorλ₯Ό μ¬μ©νμ¬ auth λ° admin μ μ μ€λ₯λ₯Ό κ΄λ¦¬νκ³ μμ΅λλ€. κ·Έλ¬λ κ·Έκ²μ μ¬μ©νλ©΄ λ΄ μ½μμ catch λ©μλκ° μ€λ₯λ₯Ό λ°ννμ§ μμ΅λλ€.
λͺ¨λ μ€λ₯κ° apollo-link-errorλ₯Ό κ±°μ³ νΈμΆμ λ©μλλ‘ λ€μ μ λ¬λμ§ μλ κ²μ²λΌ 보μ λλ€.
μΌλΆ μ€λ₯λ λ‘컬μμ κ΄λ¦¬νκ³ μΌλΆ μ€λ₯λ μ μμ μΌλ‘ κ΄λ¦¬ν μ μλλ‘ νΈμΆμμκ² μ€λ₯λ₯Ό λ°ννλ λ°©λ²μ΄ μμ΅λκΉ?
λ΄ μ±μλ κ°μ λ¬Έμ κ° μμ΅λλ€. μ€λ₯ λ§ν¬μ λͺ¨λ μ€λ₯λ₯Ό ν¬μ°©νκ³ μΆμ§λ§(μλ₯Ό λ€μ΄ κΈ°λ‘ν μ μλλ‘) μ€λ₯λ₯Ό μλ νΈμΆμμκ² μ λ¬νκ³ μ¬μ©μμκ² νμν΄μΌ νλ μ¬μ©μ μ§μ μ€λ₯ λ©μμ§κ° ν¬ν¨λ μ μμΌλ―λ‘ κ±°κΈ°μμ μ²λ¦¬νκ³ μΆμ΅λλ€. .
λ΄ μ½λ:
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path }) => {
console.log(`[GraphQL error]: ${message}, Location: ${locations}, Path: ${path}`);
},
);
}
});
const client = new ApolloClient({
link: authLink.concat(errorLink).concat(httpLink),
cache: new InMemoryCache(),
});
loginMutation({ variables: { data } })
.then(({ data, errors }) => {
if (errors) {
// I WANT TO BE ABLE TO READ ERROR MESSAGE HERE SO I CAN DISPLAY IT TO THE USER
} else if (data) {
....
}
});
forward
λ₯Ό νΈμΆνλ©΄ then
λν μΈμλ‘ undefinedλ₯Ό λ°ννλ―λ‘ λ°μ΄ν°λ μ€λ₯λ μκ³ errors
λ₯Ό null
μ€μ νλ―λ‘ λμμ΄ λμ§ μμ΅λλ€
@lbrdar μ΄μ λν ν΄κ²° λ°©λ²μ μ°Ύμμ΅λκΉ?
μλ π
@lbrdar μ΄κ²μ νλ λ°©λ²μ μΊμΉ(catch)λ₯Ό μ¬μ©νλ κ² μλλκΉ?
loginMutation({ variables: { data } })
.then(({ data, errors }) => {
if (errors) {
// I WANT TO BE ABLE TO READ ERROR MESSAGE HERE SO I CAN DISPLAY IT TO THE USER
} else if (data) {
....
}
}).catch(errors => {
});
@lbrdar @romucci μ λ κ°μ λ¬Έμ μ μ§λ©΄νκ³ μμ΅λλ€. μ¬λ¬λΆ, κ²°κ΅ ν΄κ²°νμ ¨λμ?
@Nosherwan λ°©κΈ λ²μ 1.1.11μ μ€μΉνκ³ μ΄μ λͺ¨λ κ²μ΄ μ μλν©λλ€... λ΄λΆ μ½μμ νμΈν μλ μμ΅λλ€(μ΄λκ° λ€λ₯Έ μ½μ μμ μ½μμ λ°ννλ κ²μ μμμ μλ μμ)
@merksam λ, λκΈ κ°μ¬ν©λλ€.
λλ λΉμ κ³Ό λκ°μ λ²μ μ μ¬μ©νκ³ μμ΅λλ€. λΆννλ λμμ λμΌν©λλ€.
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path }) => {
console.log(`[GraphQL error]: ${message}, Location: ${locations}, Path: ${path}`);
},
);
}
});
μμ μ½λ λΈλ‘μμ graphQLErrorsκ° ν¬μ°©λκ³ onError νΈλ€λ¬μμ λκ°λ₯Ό ν μ μμ΅λλ€. κ·Έλ¬λ μ΄λ¬ν μ€λ₯λ μ€μ νΈμΆ μ½μμΌλ‘ μ λ¬λμ§ μμ΅λλ€.
λλ λΉλκΈ° ν¨μλ₯Ό μ¬μ©νκ³ μμΌλ―λ‘ 'then' λμ await ν€μλλ₯Ό μ¬μ©νκ³ μμΌλ©° μ΄λ try catch λΈλ‘ μμ μμ΅λλ€.
catch λΈλ‘μ μ€λ₯λ₯Ό ν¬μ°©νμ§λ§ μ λ¬λ μ€λ₯λ μμ΅λλ€.
λκ΅°κ° μ΄μ λν ν΄κ²° λ°©λ²μ μ°Ύμμ΅λκΉ?
@Nosherwan @prem-prakash μ±ν μΌλ‘ μ°λ½νκ±°λ μ νλ₯Ό κ±Έμ΄ λ΄ κ²½μ°μλ μλνκ³ κ·νμ κ²½μ°μλ μλνμ§ μλ μ΄μ λ₯Ό μμλ΄λ €κ³ ν μ μμ΅λκΉ? (μ¬μ ν κ΄λ ¨μ±μ΄ μλ κ²½μ°)
μ΄μν ν΄κ²°μ± μ μ°Ύμμ§λ§ λ€μκ³Ό κ°μ΅λλ€.
μ΄κ²μ λ©μμ§λ₯Ό μΈμν©λλ€
updateProfile: function() {
this.$apollo
.mutate({
mutation: UPDATE_PROFILE,
variables: current_user
})
.catch((error) => {
console.log("this prints just the message", error);
});
}
κ·Έλ¬λ μ΄κ²μ μ€λ₯μ μ 체 λ΄μ©μ μΈμν©λλ€.
updateProfile: function() {
this.$apollo
.mutate({
mutation: UPDATE_PROFILE,
variables: current_user
})
.catch(({ graphQLErrors }) => {
console.log("this prints the full content of 'errors'", graphQLErrors);
});
}
μ΄ λ¬Έμ λ λ«μ μ μλ€κ³ μκ°ν©λλ€
@Nosherwan @romucci @Sceat @lbrdar
μ΄κ²μ λ¬Έμμ μΆκ°νλ κ²μ μ΄λ»μ΅λκΉ?
μ£μ‘νμ§λ§ μμ μ루μ μ΄ μλνμ§ μμ΅λλ€. λ§ν¬ μ€λ₯μ graphqlErrorsλ₯Ό μ΄κΈ° νΈμΆμμκ² λ€μ 보λ΄λ λ°©λ²μ λν μ 체 μλ₯Ό μκ°ν©λλ€.
νμμ κ²½μ° μ€λ₯κ° λ°μνλ©΄ λ€μ ApolloQueryResult κ°μ²΄κ° onErrorμμ μ½μλ§λ μ€λ₯ μΈλΆ μ 보λ₯Ό μ»μ§ λͺ»ν©λλ€. μλ μ€ μΌλΆλ ... ν΅νλ₯Ό λλ¬μΈκ³ μμ΅λλ€. μλ²μμ graphqlError μΈλΆ μ 보λ₯Ό κ°μ Έμ¬ μ μμ΅λλ€. κ·Έλ₯ "400 μ€λ₯"..
const gqlResult: ApolloQueryResult<IGReturnData<
IAllDataTypes
>> = await apolloClient.query<IGReturnData<IAllDataTypes>, TVariables>({
query: queryGql,
variables: queryVariables,
errorPolicy: "all",
});
μλ² κ΅¬μ±:
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
if (networkError) console.log(`[Network error]: ${networkError}`);
});
const httplink = new HttpLink({
uri: "/graphql",
credentials: "include",
});
const links = [errorLink, httplink];
export const apolloClient = new ApolloClient({
link: ApolloLink.from(links),
cache: new InMemoryCache({ addTypename: false, fragmentMatcher }),
});
@prem-prakash κ°μ¬ν©λλ€.... ꡬμμ..
μ΄ λ¬Έμ λ λ§€μ° μ§μμ μ
λλ€. λ΄ νλ‘μ νΈμ graphql μλ²λ μ μ΄ν μ μκ³ ν΄λΌμ΄μΈνΈλ§ μ μ΄ν μ μμ΅λλ€. μλ²λ μ¬λ°λ₯Έ λͺ¨μμ graphql μ€λ₯λ‘ μλ΅νμ§λ§ μν μ½λλ 400μ
λλ€. μ€λ₯ λ§ν¬μμ graphQLErrors
μ‘μΈμ€ν μ μμ§λ§ κ΅¬μ± μμ λ³νμμ @prem-prakashμμ μ μν λλ‘ graphQLErrors
λ₯Ό λΉΌλΌ λ graphQLErrors
λ λΉ λ°°μ΄μ
λλ€. . κΈ°λ³Έ λ©μμ§ "μ€λ₯: λ€νΈμν¬ μ€λ₯: μλ΅ μ€ν¨: μμ μν μ½λ 400"μλ§ μ‘μΈμ€ν μ μμ΅λλ€. Apolloλ 400 μν μ½λκ° Apolloμ λ§μΉ¨νμ΄κΈ° λλ¬Έμ μλ²μμ μ¬λμ΄ μ½μ μ μλ μ€λ₯ λ©μμ§("μ¬μ©μ λλ μνΈκ° μ¬λ°λ₯΄μ§ μμ")λ₯Ό λ°©ν΄νκ³ μμ΅λλ€.
μ€λ₯ λ©μμ§κ° ν¬ν¨λ 400 μν μ½λ μλ΅μ μ±κ³΅μ μΌλ‘ μ²λ¦¬νκ³ ν΄λΉ λ©μμ§λ₯Ό λμ°λ³μ΄λ₯Ό νΈμΆν κ΅¬μ± μμμ UIμ μ λ¬ν μ μλ μ¬λμ΄ μμ΅λκΉ?
μ’μ, λλ κ½€ λΆν©λ¦¬ν μ κ·Ό λ°©μμ κ°μ§κ³ μμ§λ§ μλνκ³ μμ΅λλ€.
μΊμμ λΆμΈ hasGraphError
λ₯Ό μ€μ νκ³ μ€λ₯ λ©μμ§λ μΊμν©λλ€.
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.forEach(error => {
// log gql error(s)
console.log("[GraphQL error]: ", error);
// cache error
client.writeData({
data: {
hasGraphError: true,
currentGraphError: error.message
}
});
});
}
if (networkError) {
// log network errors
console.log("[Network error]: ", networkError);
}
});
κ·Έλ° λ€μ MutationError κ΅¬μ± μμμμ μΊμμ μ€λ₯ λ° μ€λ₯ λ©μμ§κ° μλμ§ μΏΌλ¦¬νκ³ μ‘°κ±΄λΆλ‘ gql μ€λ₯ λλ μ€μ λ€νΈμν¬ μ€λ₯λ₯Ό λ λλ§ν©λλ€.
const HAS_ERROR = gql`
query IsGraphErrorPresent {
hasGraphError <strong i="11">@client</strong>
currentGraphError <strong i="12">@client</strong>
}
`;
export default function MutationError({ error }) {
const { data } = useQuery(HAS_ERROR);
const defaultErrorMessage =
"We're having trouble connecting. Please check your internet connection and try again.";
// real network error
if (error && error.message.includes("Failed to fetch")) {
return <Error>{defaultErrorMessage}</Error>;
}
// graph error
if (error && data && data.hasGraphError) {
return <Error>{data.currentGraphError}</Error>;
}
// probably a real server/network error
if (error) {
return <Error>{defaultErrorMessage}</Error>;
}
return null;
}
λ΄ μλ²κ° _νμ_ 200 + graphql μ€λ₯κ° λμ΄μΌ νλ κ²μ λν΄ 400μ λ°ννκΈ° λλ¬Έμ μ΄κ²μ λͺ¨λ λμ°λ³μ΄μ νμνκΈ° λλ¬Έμ μ μμ μΌ κ²μ λλ€(λλ κ·Έκ²μ λν΄ μ½κ° μ§ ν©λλ€)...
μ¬κΈ°μ μ€μν μ μ λͺ¨λ κ΅¬μ± μμ λ³νμμ Apolloμ μ²λ¦¬λμ§ μμ μμΈλ₯Ό λ°©μ§νλ λΉ onError μ½λ°±μ μ¬μ©νλ€λ κ²μ λλ€. μ±κ³΅νλ©΄ μΊμμμ hasGraphError λΆμΈμ μ¬μ€μ ν΄μΌ νλ€λ κ²μ κΈ°μ΅ν΄μΌ ν©λλ€.
const [someMutation, { loading, error, client }] = useMutation(SOME_MUTATION, {
onError() {
// this callback prevents apollo from throwing
// ...unhandled exception on 400 status code
},
onCompleted({ someMutation }) {
client.writeData({
data: {
hasGraphError: false
}
});
}
});
κ·Έλ° λ€μ λμ°λ³μ΄ μ€λ₯ κ΅¬μ± μμλ useMutation μ€λ₯λ₯Ό μνμΌλ‘ μ¬μ©ν©λλ€(λ λ€ μ€μ λ€νΈμν¬ μ€λ₯λ₯Ό κ²°μ ν μ μκ² νκ³ μλͺ»λ κ΅¬μ± μμμμ μ μ μΊμλ gql μ€λ₯λ₯Ό λ λλ§νμ§ μλλ‘ ν©λλ€).
{loading && <Spinner />}
{error && <MutationError error={error} />}
λ΄κ° λ§νλ―μ΄ μ΄ μ κ·Ό λ°©μμ λ§€μ° λΉν©λ¦¬μ μ΄μ§λ§ νμ¬ ν΄κ²°νκΈ° μν΄ λ Έλ ₯νκ³ μμ΅λλ€.
μ½λ©λ μ΄ μ κ·Ό λ°©μμ λ¬Έμ : μ΄λ μ΄λ μ΄μ λ§μ§λ§ GQL μ€λ₯λ₯Ό μΊμμ κΈ°λ‘νλ―λ‘ λμμ μ¬λ¬ GQL μ€λ₯λ₯Ό μ§μνμ§ μμ΅λλ€. μ΄κ²μ μ€λ₯ λ°°μ΄μ μμ±νκ³ μ΄λ₯Ό μΊμμ μ μ₯νμ¬ κ΄λ¦¬νκΈ°κ° μλΉν μ¬μμΌ νμ§λ§ μ΄λ₯Ό μννλ €λ©΄ λ‘컬 μ€ν€λ§/리쑸λ²λ₯Ό μ μνκ±°λ μ μ¬μ μΌλ‘ JSON.stringifyλ₯Ό μ¬μ©νμ¬ μ μ₯ν΄μΌ ν©λλ€. λ¬Έμμ΄λ‘ μΊμν©λλ€. λν λΆμΈ κ°μ falseλ‘ μ€μ νλ λμ μ±κ³΅ μ μΊμμμ currentGraphErrorλ₯Ό μ§μμΌ ν©λλ€.
κ·Έκ²μ΄ λκ΅°κ°λ₯Ό λκΈ°λ₯Ό λ°λλλ€!
λν λμμ΄ λλ κ²½μ° errorPolicyλ νμ¬ useMutation νν¬μμ μλνμ§ μμ΅λλ€. μ΄κ²μ λ²κ·Έμ΄λ©° μ΅κ·Ό μ΄ PRμμ ν΄κ²°λμμ΅λλ€: https://github.com/apollographql/apollo-client/pull/5863 νμ§λ§ νμ¬ μΆμλμ§ μμμ΅λλ€.
μ΄μ λν κ°λ°μμ μ§μ μ¬νμ΄ μμ΅λκΉ?
κ°μ₯ μ μ©ν λκΈ
μ΄μν ν΄κ²°μ± μ μ°Ύμμ§λ§ λ€μκ³Ό κ°μ΅λλ€.
μ΄κ²μ λ©μμ§λ₯Ό μΈμν©λλ€
κ·Έλ¬λ μ΄κ²μ μ€λ₯μ μ 체 λ΄μ©μ μΈμν©λλ€.
μ΄ λ¬Έμ λ λ«μ μ μλ€κ³ μκ°ν©λλ€
@Nosherwan @romucci @Sceat @lbrdar