【问题标题】:How do I add firebase to my react project?如何将 firebase 添加到我的 react 项目中?
【发布时间】:2021-09-05 09:40:06
【问题描述】:

我在 Medium 上找到了一篇文章,它使用 React 和 Firebase 开发 Todolist 应用程序。按照文章中的说明,我安装了所有需要的依赖项,创建了 React 应用程序并复制粘贴到代码中。然后我还去了 Firebase 并添加了文章 https://medium.com/@sarahzhan/building-a-todo-app-with-crud-operations-using-firebase-react-hooks-and-material-ui-caf4b1f2ecbc 中指定的集合。但是,当我运行开发服务器时,我收到一条错误消息:

./src/App.js
Module not found: Can't resolve 'firebase' in {folder-name}

所以我的问题是,我该如何解决这个问题,我做错了什么?

这是代码,以防有帮助:

firebase.js

import firebase from "firebase";

    const firebaseApp = firebase.initializeApp({
      apiKey: "xxxxxxxxxxxxxxxxxxxxxxx",
      authDomain: "xxxxxxxxxxxxxxxxxxx",
      projectId: "xxxxxxxxxxxxxxxxxxx",
      storageBucket: "xxxxxxxxxxxxxxxxx",
      messagingSenderId: "xxxxxxxxxxxxxx",
      appId: "xxxxxxxxxxxxxxxxxxx",
    });
    
    const db = firebaseApp.firestore();
    
    export default db;

App.js

import React, { useState, useEffect } from "react";
import {
  Button,
  FormControl,
  InputLabel,
  Input,
  FormHelperText,
} from "@material-ui/core";
import firebase from "firebase";

import Todo from "./Todo";
import db from "./firebase";

function App() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState("");

  // when the app loads, we need to listen to firebase
  // fetch new todos as they get added/removed
  useEffect(() => {
    // this fires when the app.js loads
    // everytime the db changes, it snaps it and give you that snapshot
    db.collection("todos")
      .orderBy("timestamp", "desc")
      .onSnapshot((snapshot) => {
        // this gives back an array
        setTodos(
          snapshot.docs.map((doc) => ({
            id: doc.id,
            todo: doc.data().todo,
          }))
        );
      });
  }, []);

  const addTodo = (event) => {
    event.preventDefault();

    db.collection("todos").add({
      todo: input,
      timestamp: firebase.firestore.FieldValue.serverTimestamp(),
    });
    // empty input after the todo is successfully stored in firebase
    setInput("");
  };

  return (
    <div className="App">
      <h1>Hello World!!!</h1>
      <form>
        <FormControl>
          <InputLabel>
            <span role="img" aria-label="emoji">
              ✅
            </span>
            Write a Todo
          </InputLabel>
          <Input value={input} onChange={(e) => setInput(e.target.value)} />
          <FormHelperText>We'll make you productive</FormHelperText>
        </FormControl>

        <Button
          disabled={!input}
          type="submit"
          variant="contained"
          color="primary"
          onClick={addTodo}
        >
          Add Todo
        </Button>
      </form>

      <ul>
        {todos.map((todo) => (
          <Todo todo={todo} />
        ))}
      </ul>
    </div>
  );
}

export default App;

Todo.js

import React, { useState } from "react";
import {
  List,
  ListItem,
  ListItemText,
  ListItemAvatar,
  Button,
  Modal,
} from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
// import "./Todo.css";

import db from "./firebase";

const useStyles = makeStyles((theme) => ({
  paper: {
    position: "relative",
    left: 400,
    width: 600,
    backgroundColor: theme.palette.background.paper,
    boxShadow: theme.shadows[5],
    padding: theme.spacing(2, 4, 3),
  },
  button: {
    width: 150,
    margin: "10px",
  },
}));

const Todo = (props) => {
  const classes = useStyles();
  const [open, setOpen] = useState(false);
  const [input, setInput] = useState();

  const handleOpen = () => {
    setOpen(true);
  };

  const updateTodo = () => {
    db.collection("todos").doc(props.todo.id).set(
      {
        todo: input,
      },
      // prevents you to overwrite/remove it, instead update it
      { merge: true }
    );
    setOpen(false);
  };
  return (
    <>
      <Modal open={open} onClose={(e) => setOpen(false)}>
        <div className={classes.paper}>
          <h3>Update the Task</h3>
          <input
            placeholder={props.todo.todo}
            value={input}
            onChange={(e) => setInput(e.target.value)}
          />
          <Button
            variant="contained"
            color="default"
            onClick={updateTodo}
            className={classes.button}
          >
            Update ✔
          </Button>
        </div>
      </Modal>
      <List className="todo__list">
        <ListItem>
          <ListItemAvatar></ListItemAvatar>
          <ListItemText
            primary={props.todo.todo}
            secondary="Uploaded Task ???? "
          />
        </ListItem>

        <button onClick={(e) => setOpen(true)}>Edit</button>

        <Button
          onClick={(e) => db.collection("todos").doc(props.todo.id).delete()}
        >
          DELETE
        </Button>
      </List>
    </>
  );
};

export default Todo;

这些是我的依赖。

"dependencies": {
    "@material-ui/core": "^4.12.3",
    "@material-ui/icons": "^4.11.2",
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "dotenv": "^10.0.0",
    "firebase": "^9.0.1",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.1.2"
  },

任何帮助都会非常有帮助。

【问题讨论】:

标签: javascript reactjs firebase google-cloud-firestore


【解决方案1】:

由于版本从firebase 8 更改为firebase 9.0,您必须使用新命令在您的应用程序中添加firebase 你可以在他们的官方网站https://firebase.google.com/docs/web/modular-upgrade找到有用的命令

之前:版本 8




import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';


之后:版本 9 兼容

// v9 compat packages are API compatible with v8 code
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';

【讨论】:

  • 我必须将 import firebase from 'firebase/compat/app'; 添加到 firebase.js 文件和 App.js 文件中。
  • 仅在 firebase.js 中
  • 我试过了,但没有用。将其添加到我的 App.js 文件中后,它就可以工作了。
  • 只需添加 firebase.js 并导出 firebase 以在其他脚本中使用 import firebase from 'firebase/compat/app'export firebase
【解决方案2】:

这是一个小要点,我用钩子代替 react-firebase-hooks,希望它会有用,如果有人想提出建议,我愿意接受。

现在您必须通过函数设置集合和文档引用,而不是从您从初始化应用创建的 firestore 实例中链接。

这里几乎是一个sn-p:

import { fs } from "../config/firebase"; // const fs = useFirestore() from the initializeApp config
import { collection, query, where, getDocs, limit, WhereFilterOp } from "firebase/firestore";

import useInterval from "./useInterval";

export interface IQuery {
  ref: string;
  operator: WhereFilterOp;
  value: any;
}

const useFirestore = (
  collectionString: string = "defaultCollection",
  limitNumber: number = 100,
  queryData?: IQuery
) => {
  const [data, setData] = useState<any[] | void>([]);

  // Instead of using the snapshot directly, im throttling the data updating to a second.
  useInterval(async () => {
    const result = await querySnapshot;
    setData(result);
  }, 1000);

  // Create a query against the collection.
  const q = queryData
    ? query(
        collection(fs, collectionString),
        where(queryData?.ref, queryData?.operator, queryData?.value),
        limit(limitNumber)
      )
    : query(collection(fs, collectionString), limit(limitNumber));

  const querySnapshot = getDocs(q)
    .then((snapshot) => {
      const data: any[] = snapshot.docs.map((doc) => {
        return {
          id: doc.id,
          ...doc.data(),
        };
      });
      return data;
    })
    .catch((error) => {
      console.error("Error getting documents: ", error);
    });

  return { data };
};

export default useFirestore;

你可以这样称呼它:

const { data: alias } = useFirestoreQuery("collection");
const { data: alias } = useFirestoreQuery("collection", 50 //limit);
const { data: alias } = useFirestoreQuery("collection", 10, {
ref: "location",
operator: "==",
value: name,
});

GIST

【讨论】:

    猜你喜欢
    • 2021-04-01
    • 2020-08-21
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 1970-01-01
    • 2022-12-01
    • 2021-11-09
    • 1970-01-01
    相关资源
    最近更新 更多