Reputation: 109
I'd like to create a hook for adding data to a firestore database. I'm not sure if I'm misunderstanding how hooks work, or firestore works, I'm new to both.
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
Firebase API
createTeam = newTeam => {
return this.db.collection("teams").add({
...newTeam
});
};
The hook
export default function useFetch(action) {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [data, setData] = useState(null);
async function performAction(body) {
try {
setLoading(true);
setData(null);
setError(null);
const data = await action(body);
setData(data);
} catch (e) {
setError(e);
} finally {
setLoading(false);
}
}
return [{ loading, data, error }, performAction];
}
Component
const [state, runFetch] = useFetch(db.createTeam);
const { values, handleChange, isDirty, handleSubmit } = useForm({
initialValues: {
name: "",
location: ""
},
onSubmit({ values }) {
runFetch(values);
},
validate(e) {
return e;
}
});
The state.data is never set to the expected response, however, the logging after await in the fetch hook shows that I am receiving the response. Should I be doing this in useEffect? What is the appropriate way to accomplish this task via hooks/firebase?
Upvotes: 2
Views: 1759
Reputation: 31335
See if that works for you.
That's a great idea for a custom hook.
Working example on CodeSandbox:
https://codesandbox.io/s/clever-joliot-ukr1t
index.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [state, runFetch] = useFetch(mockAPICall);
function mockAPICall() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Some data from DB!");
}, 1000);
});
}
return (
<React.Fragment>
<div>Loading: {state.loading ? "True" : "False"}</div>
<div>Data: {state.data}</div>
<button onClick={() => runFetch(mockAPICall)}>Get Data</button>
</React.Fragment>
);
}
function useFetch(action) {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [data, setData] = useState(null);
async function performAction(body) {
try {
setLoading(true);
setData(null);
setError(null);
const data = await action(body);
setData(data);
} catch (e) {
setError(e);
} finally {
setLoading(false);
}
}
return [{ loading, data, error }, performAction];
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Upvotes: 1