我故意将名称字段留空(""
),以便可以在GraphQL后端上测试自定义错误表单检查。
使用Graphiql,可以很好地显示错误数组。
({String!
仅阻止null
,而不阻止""
。)
谁能解释为什么错误不会出现在实际的反应组件上以及如何解决?
PS:填充字段后,该突变就可以完美地发挥作用。它还会使用新创建的记录进行更新。
Graphiql查询窗格
mutation addEmployee(
$name: String!
$position: String!
) {
addEmployee(name: $name, position: $position) {
name
position
}
}
query getEmployees {
employees {
_id
name
position
createdAt
}
}
Graphiql查询变量:请注意空白的name
字段。
{
"name": "",
"position": "CEO",
}
Graphiql结果窗格-按预期工作。
{
"errors": [
{
"message": "Field cannot be empty",
"statusCode": 400
}
],
"data": {
"addEmployee": null
}
}
react组件中getEmployeesQuery的控制台日志显示如下:
called: true
error: undefined
fetchMore: ƒ (fetchMoreOptions)
loading: false
networkStatus: 7
refetch: ƒ (variables)
employees: (16) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
startPolling: ƒ (pollInterval)
stopPolling: ƒ ()
subscribeToMore: ƒ (options)
updateQuery: ƒ (mapFn)
variables: {}
这是我的突变:
const Mutation = new GraphQLObjectType({
name: "Mutation",
fields: {
addEmployee: {
type: EmployeeType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
position: { type: new GraphQLNonNull(GraphQLString) },
},
resolve(parent, args) {
let employee = new Employee({
name: args.name,
position: args.position,
});
let errors = [];
try {
if (!args.name) {
errors.push("name");
}
if (errors.length) throw new Error(errorName.INVALID_FIELD);
return employee.save();
} catch (err) {
throw new GraphQLError(err.message);
}
}
}
}
});
这是我的组件:
const Employees = ({
getEmployeesQuery: { employees, loading, errors },
addEmployeeMutation
}) => {
const [state, setState] = useState({
name: "",
position: "",
});
const showEmployee = id => () => {
const employee = store.state.employees.find(v => v._id === id);
};
const handleChange = name => evt => {
setState({ ...state, [name]: evt.target.value });
};
const addEmployee = () => {
addEmployeeMutation({
variables: {
name: state.name,
position: state.position,
},
refetchQueries: [{ query: getEmployeesQuery }]
});
};
return (
<div className={styles.root}>
<h2>Employees</h2>
<div className={styles.listContainer}>
<header>
<div>Employee Name</div>
<div>Position</div>
</header>
<div className={styles.list}>
{!loading ? (
employees.map(v => (
<Employee
key={v._id}
showEmployees={showEmployees(v._id)}
position={v.position}
id={v._id}
/>
))
) : (
<Loader />
)}
</div>
</div>
{(errors || []).map((error, i) => (
<div>{error.message}</div>
))}
<EmployeeForm
fields={state}
handleChange={handleChange}
submit={addEmployee}
/>
</div>
);
};
Employees.propTypes = {
classes: PropTypes.object,
route: PropTypes.string,
name: PropTypes.string
};
export default compose(
getEmployeesQuery,
addEmployeeMutation
)(Employees);
查询:
import { gql } from "apollo-boost";
import { graphql } from "react-apollo";
export const getEmployeesQuery = graphql(
gql`
{
employees {
_id
createdAt
name
position
}
}
`,
{ name: "getEmployeesQuery" }
);
export const addEmployeeMutation = graphql(
gql`
mutation(
$name: String!
$position: String!
) {
addEmployee(
name: $name
position: $position
) {
_id
createdAt
name
position
}
}
`,
{ name: "addEmployeeMutation" }
);
这越来越长,但这是最后一个。诺言。 这是index.js!
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import "./index.css";
import App from "./layout/App";
import * as serviceWorker from "./serviceWorker";
import { ApolloProvider } from "react-apollo";
import { ApolloClient } from "apollo-client";
import { createHttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
const httpLink = createHttpLink({
uri: "http://localhost:4000/graphql"
});
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache()
});
ReactDOM.render(
<ApolloProvider client={client}>
<BrowserRouter>
<App />
</BrowserRouter>
</ApolloProvider>,
document.getElementById("root")
);
serviceWorker.register();
答案 0 :(得分:0)
这个问题很基本。但是对于那些陷入同样愚蠢陷阱的人。 。 。
确保对提交事件运行preventDefault()
。默认操作会在提交时重新加载仅运行getEmployeesQuery
的页面。这就是addEmployeeMutation
上不存在任何内容的原因。
preventDefault
强制addEmployeeMutation
返回错误。
还要确保在尝试/捕获中捕获错误。它们不包含在道具中。 (谢谢Long Nguyen)。
const [errors, setErrors] = useState([]);
const addEmployee = async evt => {
evt.preventDefault(); // This fixed it!
try {
await addEmployeeMutation({
variables: {
name: state.name,
position: state.position,
},
refetchQueries: [{ query: queries.getEmployeesQuery }]
});
} catch (e) {
setErrors([e.message]);
}
};