【问题标题】:React State Storing & Outputting Duplicate ValuesReact 状态存储和输出重复值
【发布时间】:2019-06-09 22:18:10
【问题描述】:

这里的小问题我认为解决起来相对简单,但我无法完全理解。我对 React 很陌生。我决定制作一个小型示例应用程序,它只从两个字段中获取输入,将它们保存到 Firebase 并在页面上输出这些值。它在提交数据和检索数据方面工作得很好,但是当我单击提交按钮将数据添加到 Firebase 时,它​​似乎复制了存储在状态中的数据并呈现两次:

父组件:

import React, { Component, Fragment } from 'react';

import firebase from '../../config/firebase';
import QuestFormField from './QuestFormField/QuestFormField';
import QuestFormSelection from './QuestFormSelection/QuestFormSelection';

import classes from './QuestForm.css';

class QuestForm extends Component {
    state = {
        value: '',
        points: 0,
        items: []
    }

    questHandler = e => {
        this.setState({
            value: e.target.value,
        });
    }

    pointsHandler = e => {
        this.setState({
            points: e.target.value,
        });
    }

    submitHandler = e => {
        e.preventDefault();
        const itemsRef = firebase.database().ref('quest');
        const items = {
            quest: this.state.value,
            points: this.state.points
        }
        itemsRef.push(items);
        this.setState({
            value: '',
            points: 0
        });
    }

    render () {
        return (
            <Fragment>
                <form className={classes.Form} onSubmit={this.submitHandler}>
                    <QuestFormField val='Quest' inputType='text' name='quest' value={this.state.value} changed={this.questHandler} />
                    <QuestFormField val='Points' inputType='number' name='points' value={this.state.points} changed={this.pointsHandler} />
                    <button>Away! To Firebase!</button>
                </form>
                <QuestFormSelection />
            </Fragment>
        );
    }

}

export default QuestForm;

子组件(表单域)

import React from 'react';

import classes from './QuestFormField.css';

const QuestFormField = (props) => (
    <div className={classes.Container}>
        <label htmlFor={props.name}>{props.val}</label>
        <input type={props.inputType} name={props.name} onChange={props.changed}/>
    </div>
);

export default QuestFormField;

子组件 B(数据检索器/显示器)

import React, { Component, Fragment } from 'react';

import firebase from '../../../config/firebase';

import classes from './QuestFormSelection.css';

class QuestFormSelection extends Component {
    state = {
        quests: []
    }

    componentDidMount() {
        const database = firebase.database();
        const quests = [];

        database.ref('quest').on('value', (snapshot) => {
            snapshot.forEach((childSnapshot) => {
                quests.push({
                    id: childSnapshot.key,
                    quest: childSnapshot.val().quest,
                    points: childSnapshot.val().points,
                });
            });
            console.log(quests);
            this.setState(() => {
                return {
                    quests: quests
                }
            });
            console.log(this.state.quests);
        });
    }

    render () {
        return (
            <section className='display-item'>
                <div className="wrapper">
                    {this.state.quests.map(quest => (
                        <div key={quest.key}>
                            <p>{quest.quest}</p>
                            <p>{quest.points}</p>
                        </div>
                    ))}
                </div>
            </section>
        )
    }
} 

export default QuestFormSelection;

此处的行为示例:

https://i.gyazo.com/c70972f8b260838b1673d360d1bec9cc.mp4

任何指针都会有所帮助:)

【问题讨论】:

标签: javascript reactjs firebase state


【解决方案1】:

我自己没有使用过 firebase,但看起来下面的代码正在设置一个侦听器来监听每次发生更改时都会执行的“请求”更改,但是您在 db 更改处理程序之外定义了 const quests = []。这意味着在第二次更改时,您会将快照中的所有内容推送到相同的 quests 数组中,该数组可能已经添加了以前的快照。我相信您可以通过在侦听器函数中移动quests 变量来解决此问题,如下所示。

componentDidMount() {
    const database = firebase.database();

    database.ref('quest').on('value', (snapshot) => {
        const quests = [];
        snapshot.forEach((childSnapshot) => {
            quests.push({
                id: childSnapshot.key,
                quest: childSnapshot.val().quest,
                points: childSnapshot.val().points,
            });
        });
        console.log(quests);
        this.setState(() => {
            return {
                quests: quests
            }
        });
        console.log(this.state.quests);
    });
}

【讨论】:

  • 你是对的。这正是它正在做的事情。它只是在顶部添加新输入并重新渲染。谢谢你。
猜你喜欢
  • 2016-04-21
  • 2018-06-19
  • 1970-01-01
  • 2020-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-21
  • 2020-05-13
相关资源
最近更新 更多