反应状态存储输出重复值 [英] React State Storing & Outputting Duplicate Values

查看:66
本文介绍了反应状态存储输出重复值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为这是一个相对容易解决的小问题,但我无法完全解决.我对React很新.我决定制作一个小示例应用程序,该应用程序仅接收来自两个字段的输入,然后将它们保存到Firebase并在页面上输出这些值.就提交数据和检索数据而言,它工作得很好,但是当我单击提交"按钮将数据添加到Firebase时,它似乎复制了状态中存储的数据并渲染了两次:

Slight issue here which I think is relatively simple to solve but I can't quite get my head around. I'm quite new to React. I've decided to make a small sample app which just takes the input from two fields, saves them to Firebase and outputs those values on the page. It works completely fine in terms of submitting data and retrieving it, but when I click the submit button to add the data to Firebase it seems to duplicate the data stored in the state and render them twice:

父组件:

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(数据检索器/显示器)

Child Component B (Data Retriever/Displayer)

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

任何指针都可以帮助:)

Any pointers would help :)

推荐答案

我自己还没有使用过Firebase,但是下面的代码似乎正在设置一个侦听器来侦听请求"更改,该更改将在每次更改发生时执行,但是您在数据库更改处理程序之外定义了const quests = [].这意味着在第二次更改时,您会将快照中的所有内容推入可能已经添加了先前快照的同一quests阵列.我相信您可以通过在侦听器函数内移动quests变量来解决此问题,如下所示.

I haven't used firebase myself, but it looks like the code below is setting up a listener to "quest" changes which will execute each time a change occurs, but you defined const quests = [] outside of the db change handler. This means that on the second change, you will push everything in the snapshot to the same quests array that may have already had previous snapshots added to it. I believe you can fix this by moving the quests variable inside the listener function as shown below.

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);
    });
}

这篇关于反应状态存储输出重复值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆