ReactJS如何跨文件使用其他组件内定义的const常量
错误原因
getdgearcamoper是Weights组件内部声明的局部常量,作用域仅生效于Weights组件的函数体内,属于组件私有变量,外部的additem.js没有访问权限,直接在additem.js中引用该变量必然触发未定义报错。
另外原Weights组件本身存在两处逻辑隐患:
useMemo依赖数组缺失country项,切换国家时计算结果不会自动更新- 非
ENGLAND场景下没有返回值,getdgearcamoper会是undefined,调用toFixed时可能触发报错
解决方案
方案1:直接使用封装好的Weights组件(推荐,适合仅需要展示对应输入框的场景)
Weights组件本身已经封装了重量计算逻辑和对应的TextField渲染逻辑,不需要单独提取内部变量,只要在additem.js中渲染组件时,把组件要求的4个入参(data、country、listItemUser、gear)按要求传入即可正常展示计算结果。
示例代码(additem.js中):
import Weights from './weights' // additem对应的页面组件 function AddItemPage() { // 以下几个值替换为你additem.js中实际的业务变量即可 const [data, setData] = useState([]) const [country, setCountry] = useState({label: "ENGLAND"}) const listItemUser = {} const gear = {} return ( <div className="page-container"> {/* 其他原有业务组件 */} {/* 直接传参渲染Weights组件 */} <Weights data={data} country={country} listItemUser={listItemUser} gear={gear} /> </div> ) }
同时建议先修复weights.js里的逻辑隐患,修改后的完整代码:
import { useMemo } from 'react' const Weights = ({ data, country, listItemUser, gear }) => { const getdgearcamoper = useMemo(() => { let initialValue = 0 if (country?.label == "ENGLAND") { const gettata = data.filter(el => el.packingLocation == "Resident") return gettata.reduce( (previousValue, currentValue) => previousValue + Number(currentValue.Weight) * Number(currentValue.Quantity) , initialValue ) } // 补全非英格兰场景的默认返回值 return initialValue // 补全依赖项 }, [data, country]); return ( <TextField disabled InputLabelProps={{ shrink: true, }} id="standard-basic" label="PERSON" value={getdgearcamoper.toFixed(0)} name="campertotalinput" type="number" variant="outlined" /> ) } export default Weights
方案2:通过回调向父组件透传计算值(适合需要在additem.js中复用计算结果做其他业务逻辑的场景)
如果除了展示Weights自带的输入框,还需要在additem.js其他位置用到这个重量计算结果,可以给Weights组件新增一个回调prop,计算完成后把值抛给父组件使用。
改造后的weights.js代码:
import { useMemo, useEffect } from 'react' const Weights = ({ data, country, listItemUser, gear, onGetCalculatedWeight }) => { const getdgearcamoper = useMemo(() => { let initialValue = 0 if (country?.label == "ENGLAND") { const gettata = data.filter(el => el.packingLocation == "Resident") return gettata.reduce( (previousValue, currentValue) => previousValue + Number(currentValue.Weight) * Number(currentValue.Quantity) , initialValue ) } return initialValue }, [data, country]); // 计算值变化时触发回调,把值传给父组件 useEffect(() => { onGetCalculatedWeight?.(getdgearcamoper) }, [getdgearcamoper, onGetCalculatedWeight]) return ( <TextField disabled InputLabelProps={{ shrink: true, }} id="standard-basic" label="PERSON" value={getdgearcamoper.toFixed(0)} name="campertotalinput" type="number" variant="outlined" /> ) } export default Weights
additem.js中使用示例:
import { useState } from 'react' import Weights from './weights' function AddItemPage() { const [data, setData] = useState([]) const [country, setCountry] = useState({label: "ENGLAND"}) const listItemUser = {} const gear = {} // 存储从Weights组件拿到的计算值 const [calculatedWeight, setCalculatedWeight] = useState(0) return ( <div className="page-container"> {/* 其他业务组件,此处可以直接使用calculatedWeight做逻辑计算、展示等 */} <Weights data={data} country={country} listItemUser={listItemUser} gear={gear} onGetCalculatedWeight={(val) => setCalculatedWeight(val)} /> </div> ) }
内容的提问来源于stack exchange,提问作者Paul VI
相关产品推荐
相关产品推荐

