Reputation: 1668
I have a MongoDB database hosted in MongoDB Atlas, I am using MongoDB Atlas RealM as well to create GraphQL schemas.
I am consuming the GraphQL API in react js application created using Next JS.
I am also using useSWR
hooks to fetch the data. With useSWR
I don't have any issues fetching the data but when it comes to running the mutation queries using useSWR
I am unable to get it done.
There is no proper documentation on how to do it.
Here is my code
//@ts-nocheck
import React, { useContext, useEffect, useState } from "react";
import { Drawer, Button, Form, Input, Select, Cascader } from "antd";
import { TRANSACTION_TYPES } from "queries/transactionTypes";
import { LIST_CATEGORIES } from "queries/categories";
import { FINANCIAL_ACCOUNTS } from "queries/financialAccounts";
import { PAYMENT_MODES } from "queries/paymentModes";
import { INSERT_TRANSACTION } from "queries/transaction";
import useSWR from "swr";
import { AuthContext } from "context/AuthContext";
const AddTransaction = () => {
const userId = useContext(AuthContext);
const { Option } = Select;
const [visible, setVisible] = useState(true);
const [txnType, setTxnType] = useState();
const { data: txnTypeData } = useSWR(TRANSACTION_TYPES);
const { data: categories } = useSWR(LIST_CATEGORIES);
const { data: accounts } = useSWR([FINANCIAL_ACCOUNTS, { user_id: userId }]);
const { data: modes } = useSWR(PAYMENT_MODES);
const { data: transaction, mutate } = useSWR(INSERT_TRANSACTION);
if (txnTypeData && txnTypeData.error) {
return <p>An error occurred: ${txnTypeData.error}</p>;
}
const txnTypes = txnTypeData ? txnTypeData.data.transaction_types : null;
console.log("transaction", transaction);
const options = categories
? categories.data.categories.map((cat) => {
let children = [];
cat.subcategories.forEach((subcat) =>
children.push({
value: subcat,
label: subcat,
})
);
return {
value: cat.name,
label: cat.name,
children,
};
})
: null;
const showDrawer = () => {
setVisible(true);
};
const onClose = () => {
setVisible(false);
};
const handleTxnType = (value) => {
setTxnType(value);
};
const onFinish = (values) => {
const txnData = {};
txnData.date = new Date();
txnData.user_id = userId;
txnData.category = values.category[0];
txnData.subcategory = values.category[1];
txnData.type = values.txntype;
txnData.amount = values.amount;
txnData.description = values.description;
txnData.mode = values.mode;
txnData.account = {
account_name: "ICICI bank",
bank_name: "ICICI bank",
type: "savings",
};
console.log("txnData", txnData);
mutate([INSERT_TRANSACTION, { data: txnData }]);
};
return (
<>
<Button type="primary" onClick={showDrawer}>
Open
</Button>
<Drawer
title="Add Transaction"
placement="right"
onClose={onClose}
visible={visible}
>
<Form
layout={"vertical"}
initialValues={{ remember: true }}
onFinish={onFinish}
autoComplete="off"
>
<Form.Item label="Txn Type" name="txntype">
<Select onChange={handleTxnType}>
{txnTypes &&
txnTypes.map((type) => (
<Option key={type._id} value={type.type}>
{type.type}
</Option>
))}
</Select>
</Form.Item>
<Form.Item label="Cateogry / Subcategory" name="category">
<Cascader options={options} placeholder="Please select" />
</Form.Item>
<Form.Item label="Description" name="description">
<Input placeholder="Proper description of the expense" />
</Form.Item>
<Form.Item label="Amount(₹)" name="amount">
<Input placeholder="Amount" />
</Form.Item>
{txnType !== "self transfer" && (
<Form.Item label="Account" name="account">
<Select>
{accounts &&
accounts.data.financial_accounts.map((acc) => (
<Option key={acc._id}>{acc.name}</Option>
))}
</Select>
</Form.Item>
)}
{txnType === "self transfer" && (
<>
<Form.Item label="From Account" name="from_account">
<Select>
{accounts &&
accounts.data.financial_accounts.map((acc) => (
<Option key={acc._id}>{acc.name}</Option>
))}
</Select>
</Form.Item>
<Form.Item label="To Account" name="to_account">
<Select>
{accounts &&
accounts.data.financial_accounts.map((acc) => (
<Option key={acc._id}>{acc.name}</Option>
))}
</Select>
</Form.Item>
</>
)}
<Form.Item label="Mode" name="mode">
<Select defaultValue="gpay">
{modes &&
modes.data.payment_modes.map((mode) => (
<Option key={mode._id} value={mode.name}>
{mode.name}
</Option>
))}
</Select>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
</Drawer>
</>
);
};
export default AddTransaction;
The problem is with this query
const { data: transaction, mutate } = useSWR(INSERT_TRANSACTION);
Here is the mutation query
export const INSERT_TRANSACTION = `
mutation INSERT_TRANSACTION($data: TransactionInsertInput!) {
insertOneTransaction(data: $data) {
_id
}
}
`;
I am calling the mutate
function in the onFinish()
like this
mutate([INSERT_TRANSACTION, { data: txnData }]);
But, I am getting an error message
message: "Variable \"$data\" of required type \"TransactionInsertInput!\" was not provided."
Not sure, why I am getting this error, as I have already been passing the $data
to the query through mutate
.
Someone, please shed some light on this, what I am doing wrong here?
Upvotes: 2
Views: 667
Reputation: 5093
useSWR
is only used to query data, and it's triggered immediatly when the component mounts, you don't want that for a data insert or update. The fact that a mutate
fn is returned it's only to revalidate, or rerun said query.
Instead use useSWRMutation
. This hook returns a trigger
fn that you can execute the moment you want your insert to run. Or simpler yet, just don't use SWR for mutations.
Upvotes: 0