【问题标题】:Reusing React components to handle a different DB collection重用 React 组件来处理不同的数据库集合
【发布时间】:2021-12-13 10:38:12
【问题描述】:

我有一个关于 React 的初学者问题。我刚刚写了这个组件:

class MovieInput extends React.Component {
  constructor(props) {
    super(props);
    firebase.initializeApp(config);
  
    this.state = {
      movies: []
    };
  }

  ....
}

它工作正常,将数据保存在 Firebase 中的一个名为 movies 的集合下。 我开始研究第二个组件,如下所示:

class BookInput extends React.Component {
  constructor(props) {
    super(props);
    firebase.initializeApp(config);
  
    this.state = {
      books: []
    };
  }

  ....
}

我已经可以看到,这两个组件的大部分代码将是相同的,因此编写两次毫无意义。所以问题来了。我怎样才能编写一个标准组件,使用我可以传递的道具,并有类似的东西:

<MediaInput type='movies'/>
<MediaInput type='books'/>

代替:

<MovieInput />
<BookInput />

新组件可能如下所示:

class MediaInput extends React.Component {
  constructor(props) {
    super(props);
    firebase.initializeApp(config);
  
    this.state = {
          // Make use of some prop to set collection adequately ....
          // This is what I don't know how to do ....
          collection: []
    };
  }

  ....
}

设置我的问题的背景可能很有用,说我受到this tutorial 的启发开始编写上面的代码。

........ 再做一些工作:

我正在尝试实现一个更通用的组件 (MediaInput)(如 srgbnd 的回答中所建议的那样)。我通过修改 MovieInput 中的代码来做到这一点(已经工作)。我在实现上仍然遇到了一些问题:

  componentDidUpdate(prevProps, prevState) {
    //if (prevState !== this.state) { // This line may need to be modified to the following.
    if (prevState.db !== this.state.db) { 
      this.writeUserData();
    }
  }

  writeUserData = () => {
    firebase.database()
      .ref("/")
      .set(this.state);
  };


  handleSubmit = event => {
    event.preventDefault();
    .....
    // These 3 lines should be modified. Probably replacing movies by something like state.db.{props.type} ???
    const { movies } = this.state;
    movies.push({ ... });
    this.setState({ movies });
    .....
  };

【问题讨论】:

    标签: reactjs firebase firebase-realtime-database


    【解决方案1】:

    我不熟悉 firebase 数据库。

    但如果我假设

    Firebase.database()
          .ref("/")
          .set(this.state);
    

    自己处理你的状态的不同键(就像每个值上的所有 CRUD 行为)这个简单的技巧应该适用于你的 type 道具:

    class MediaInput extends React.Component {
      constructor(props) {
        super(props);
        firebase.initializeApp(config);
      
        this.state = {
              // The array will have the key 'movies' or 'books'
              [props.type]: []
        };
      }
    
      ....
    }
    

    但请注意始终定义“类型”道具!

    【讨论】:

    • 你可能是对的。我使用的教程的编写方式,变量(movies)的名称恰好与数据库中的集合名称相同。这让我很难理解如何按照我需要的方式自定义代码。除非我到处更改变量。 (这是我编写第一个组件时所做的。)但目前还不清楚我需要更改哪些内容才能使其按照我现在想要的方式工作。这就是为什么我放了教程的链接,以便人们可以看到我来自哪里。
    【解决方案2】:

    首先,我会将 firebase 详细信息放入一个单独的类中以尊重 SOLID Dependency Inversion Principle。例如:

    class AppDatabase {
      constructor() {
        firebase.initializeApp(config);
      }
    
      addCollection(data) {
        return firebase.database().ref('/').set(data);
      }
    }
    

    其次,我会像你一样使用 type 属性。

    <MediaInput type='movies'/>
    <MediaInput type='books'/>
    

    最后,在组件中使用 AppDatabase。例如

    import { AppDatabase } from '../services';
    
    class MediaInput extends React.Component {
      constructor(props) {
        super(props);
        this.appDatabase = new AppDatabase();
      
        this.state = {
          db: {
            [props.type]: []
          }
        };
      }
    
      addCollection() {
        this.appDatabase.addCollection(this.state.db);
      }
    }
    

    【讨论】:

    • 我必须说我非常喜欢你建议的处理问题的方式。因此我正在尝试使用它。但这对我来说还不是很清楚。主要是最后一部分;首先,我不清楚如何在 MediaInput 类中使用 addCollection() 函数,然后(因为我不熟悉 React 语法)我还有一些关于如何转录我的工作代码的问题(在 MovieInput 中)到更通用的版本(在 MediaInput 中)。我已将这些问题添加到帖子的末尾,而不是评论中。如果你有时间,请看一下。
    猜你喜欢
    • 1970-01-01
    • 2015-01-27
    • 1970-01-01
    • 1970-01-01
    • 2012-02-18
    • 2023-03-23
    • 2013-03-22
    • 1970-01-01
    • 2019-07-15
    相关资源
    最近更新 更多