React中如何正确对Firebase获取的两个数值字段求和
问题现象
React开发过程中,对Firebase实时数据库读取到的contactObjects[id].gcc、contactObjects[id].lcc两个字段执行加法计算时,始终得到字符串拼接结果而非数值求和结果:当两个字段存储值分别为10、30时,现有代码输出10 + 30,而非预期的40。
附原问题相关实现代码:
import React, { useState, useEffect } from "react"; import ContactForm from "./ContactForm"; import firebaseDb from "../firebase"; const Contacts = () => { var [contactObjects, setContactObjects] = useState({}); var [currentId, setCurrentId] = useState(""); useEffect(() => { firebaseDb.child("contacts").on("value", (snapshot) => { if (snapshot.val() != null) setContactObjects({ ...snapshot.val(), }); else setContactObjects({}); }); }, []); const addOrEdit = (obj) => { if (currentId == "") firebaseDb.child("contacts").push(obj, (err) => { if (err) console.log(err); else setCurrentId(""); }); else firebaseDb.child(`contacts/${currentId}`).set(obj, (err) => { if (err) console.log(err); else setCurrentId(""); }); }; const onDelete = (key) => { if (window.confirm("Are you sure to delete this record?")) { debugger; firebaseDb.child(`contacts/${key}`).remove((err) => { if (err) console.log(err); else setCurrentId(""); }); } }; return ( <> <div className="jumbotron jumbotron-fluid"> <div className="container"> <h1 className="display-4 text-center">Contact Register</h1> </div> </div> <div className="row"> <div className="col-md-5"> <ContactForm {...{ addOrEdit, currentId, contactObjects }} /> </div> <div className="col-md-7"> <table className="table table-borderless table-stripped"> <thead className="thead-light"> <tr> <th>Full Name</th> <th>Mobile</th> <th>Email</th> <th>Address</th> <th>Street</th> <th>Address</th> <th>Gcc</th> <th>Lcc</th> </tr> </thead> <tbody> {Object.keys(contactObjects).map((id) => { return ( <tr key={id}> <td>{contactObjects[id].fullName}</td> <td>{contactObjects[id].mobile}</td> <td>{contactObjects[id].email}</td> <td>{contactObjects[id].address}</td> <td>{contactObjects[id].street}</td> <td>{contactObjects[id].gcc}</td> <td>{contactObjects[id].lcc}</td> <td> {contactObjects[id].gcc} + {contactObjects[id].lcc} </td> <td> <a className="btn text-primary" onClick={() => { setCurrentId(id); }} > <i className="fas fa-pencil-alt"></i> </a> <a className="btn text-danger" onClick={() => { onDelete(id); }} > <i className="far fa-trash-alt"></i> </a> </td> </tr> ); })} </tbody> </table> </div> </div> </> ); }; export default Contacts;
问题原因
两个问题共同导致结果不符合预期:
- JSX写法错误:当前代码把
+符号放在了JSX表达式的大括号外面,属于普通文本节点,最终渲染效果是依次输出gcc的值、文本+、lcc的值,根本没有执行加法运算。 - 类型不匹配:Firebase读取到的字段值默认是字符串类型,就算把
+放到大括号内执行运算,JS也会执行字符串拼接而非数值求和。
修复方案
1. 修正渲染层计算逻辑
把求和逻辑放到同一个JSX表达式大括号内,计算前先把两个字段值转为数值类型,替换原有错误的求和列代码:
<td> {/* 用Number转数值后相加,加||0兜底避免空值转成NaN */} {(Number(contactObjects[id].gcc) || 0) + (Number(contactObjects[id].lcc) || 0)} </td>
常用的数值转换方式可按需选择:
Number(val):通用转换,支持整数、浮点数parseInt(val, 10):仅转整数,需要指定进制参数10避免兼容问题parseFloat(val):转浮点数+val:隐式转换写法,代码更简洁
2. 根源优化:写入数据时统一类型
在数据写入Firebase的逻辑中提前把gcc、lcc转为数值类型存储,后续读取时无需每次做类型转换:
const addOrEdit = (obj) => { // 写入前预处理数值字段 const saveData = { ...obj, gcc: Number(obj.gcc) || 0, lcc: Number(obj.lcc) || 0 } if (currentId == "") firebaseDb.child("contacts").push(saveData, (err) => { if (err) console.log(err); else setCurrentId(""); }); else firebaseDb.child(`contacts/${currentId}`).set(saveData, (err) => { if (err) console.log(err); else setCurrentId(""); }); };
内容的提问来源于stack exchange,提问作者Iliya Shatami
相关产品推荐
相关产品推荐

