Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ReactJS警告:更改组件后遇到两个具有相同键的子级_Reactjs - Fatal编程技术网

ReactJS警告:更改组件后遇到两个具有相同键的子级

ReactJS警告:更改组件后遇到两个具有相同键的子级,reactjs,Reactjs,我创建了一个reactJS应用程序,它有一个主页和一个详细信息页,主页从一个具有字母数字唯一键的数据库中获取数据,一旦我单击详细信息页并呈现详细信息组件,但当我返回主页时警告:遇到两个具有相同键的子项 此密钥来自firebase数据库 我的App.js function App() { return ( <div className="App"> <Router> <Navbar />

我创建了一个reactJS应用程序,它有一个主页和一个详细信息页,主页从一个具有字母数字唯一键的数据库中获取数据,一旦我单击详细信息页并呈现详细信息组件,但当我返回主页时
警告:遇到两个具有相同键的子项

此密钥来自firebase数据库

我的App.js

function App() {
  return (
    <div className="App">
       <Router>
        <Navbar />
        <Route  path="/" exact component={ExpenseList} />
        <Route  path="/details/:id"   component={ExpenseDetails} />
       </Router>
    </div>
  );
}
函数应用程序(){
返回(
);
}
我的主页组件tran变量设置为全局变量

import React, {Component} from 'react';
import { Link, useHistory } from 'react-router-dom';
import {db} from '../server';
let tran = [];

componentDidMount(){
        db.collection('transactions').orderBy('added_at', 'desc').onSnapshot(snapshot => {
        let changes = snapshot.docChanges();
         changes.forEach(change => {
            if(change.type == 'added'){
         
               tran.push(change.doc);
        
                } 
            });   
          this.setState( {transactions: tran});    
                });
    }

  displayTransactions(){
    return this.state.transactions.map(transaction => {
        return <Transaction record={transaction.data()}  key={transaction.id} sequence={transaction.id} />;
        
    })
}

   render(){
      return(
        <div className="container mt-4">
            <h2>Transaction List</h2>

            <div className="mt-5" id="renderTransactions">
                {this.displayTransactions()}
            </div>

        </div>
       
    )
}
import React,{Component}来自'React';
从“react router dom”导入{Link,useHistory};
从“../server”导入{db};
设tran=[];
componentDidMount(){
db.collection('transactions').orderBy('added_at','desc').onSnapshot(快照=>{
let changes=snapshot.docChanges();
changes.forEach(change=>{
如果(change.type=='added'){
交易推送(变更单);
} 
});   
this.setState({transactions:tran});
});
}
显示事务(){
返回此.state.transactions.map(事务=>{
返回;
})
}
render(){
返回(
交易清单
{this.displayTransactions()}
)
}
我的详细信息页面

componentDidMount(){
        var docID = this.props.match.params.id;
        db.collection('transactions').doc(docID).get().then( doc => {

            let details = {
                 _id: doc.id,
                 title: doc.data().title,
                 details: doc.data().details,
                 category: doc.data().category,
                 dateTransaction: doc.data().dateTransaction,
                 amount: doc.data().amount,
                 transType: doc.data().transType,
              }

              this.setState( {transactionDetails: details});
        });
    }

transactionDetails(){
           return <TransactionDetails record={this.state.transactionDetails} deleteTransaction={this.deleteTransaction} />;     
    }

 render(){

    return(
      <div className="mt-5">
            
            <div className="container">
              <h2 className="mb-5">Transaction Details</h2>
              {this.transactionDetails()} 
            </div>
       </div>
      
      )
    
}
componentDidMount(){
var docID=this.props.match.params.id;
db.collection('transactions').doc(docID).get().then(doc=>{
让详细信息={
_id:doc.id,
标题:doc.data().title,
详细信息:doc.data().details,
类别:doc.data().category,
dateTransaction:doc.data().dateTransaction,
金额:单据数据()金额,
transType:doc.data().transType,
}
this.setState({transactionDetails:details});
});
}
交易详情(){
返回;
}
render(){
返回(
交易详情
{this.transactionDetails()}
)
}
问题 好吧,看来你们是在间接地改变状态<代码>传输
缓存所有以前获取的数据库数据

let tran = [];

componentDidMount(){
  db.collection('transactions').orderBy('added_at', 'desc').onSnapshot(snapshot => {
    let changes = snapshot.docChanges();
    changes.forEach(change => {
      if(change.type == 'added'){
         tran.push(change.doc);
      } 
    });   
    this.setState({ transactions: tran });    
  });
}
tran
看起来是局部全局的,每次组件装载时,它都会将所有更改推送到
tran
中,然后设置状态。每次安装组件时,它都会再次将所有更改推送到
tran
并设置状态。这些后续装载使用现有填充的
tran
数组,并可能推入重复数据

解决方案 我猜你是想让每一个坐骑都“新鲜”。为此,我建议将
更改映射到您的状态。由于“将返回相同的数据元素,包括新添加的数据”,您可以简单地使用整个数组,因此无需将“状态”保持在组件之外,也无需按“添加的”元素进行过滤

componentDidMount(){
  db.collection('transactions').orderBy('added_at', 'desc').onSnapshot(snapshot => {
    const changes = snapshot.docChanges();
    this.setState({ transactions: changes });    
  });
}

是否可以添加详细信息页面的
渲染
功能映射数据并使用React键?请包括一个完整的例子。什么是
tran
?在哪里申报?不管它是什么,你似乎都在变异。是的,你显然是在变异状态。你能澄清一下
change.type=='added'
的作用吗?如果组件重新安装并且调用了相同的db查询,是否返回了不同的数据元素?@drewrese fthe change.type检查firebase数据库是否等于added,每次firebase中有新数据执行时,都会返回相同的数据元素,包括新添加的数据。