You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React跨页面组件传props遇newItems空、map报错问题求助

React状态跨组件传递与渲染问题排查

在开发React应用时,我在App组件中通过[newItems, setNewItems] = useState([])声明了状态,想把它作为props传递给其他页面组件,最终在Home页面的MoneyInOutDetails组件中遍历newItems渲染列表。目前未使用数据库,但遇到两个问题:

  • 控制台显示newItems为空
  • MoneyInOutDetails组件报错“无法读取newItems的map属性”

想确认当前实现方式是否可行,以及问题出在哪里。


相关代码

MoneyIn组件

//MoneyIn Component
const MoneyIn = ({newItems, setNewItems}) => {

 let handleSaveMonyIn = (event) => {
        event.preventDefault(); 
        //setBalanceDue(balanceSet);
        if (totalAmountIn === 0 || itemDescription === "") {
            setSeverity("error")
            //setError(true);
            setMessage("Enter Amount and Item Description");
            setOpen(true)
        } else if (totalSellingPrice > totalAmountIn) {
            console.log(totalSellingPrice);
           // setError(true);
            setSeverity("error")
            setMessage("Total Selling Prices cannot be bigger than Total amount");
            setOpen(true)
        }

        else {
            const newMoneyInData = { totalAmountIn, amountRecieved, balanceDue, newItems, itemDescription };
            setMoneyInData([...moneyInData, newMoneyInData]);

            localStorage.setItem("moneyIn", JSON.stringify(moneyInData));
            document.getElementById("totalAndRecievedAmt").reset();
            document.getElementById("itemDescriptionFrm").reset();
            //setSuccess(true);
            setSeverity("success");
            setMessage("Saved Successfully !!!");
            setOpen(true);
            // setTotalAmountIn(0);
            // setAmountRecieved(0);
            // setBalanceDue(0);
            // setItemDescription('');
             // setNewItems([]);

            
            console.log(newMoneyInData);
        }
      
    }

let handleSaveItem = () => {
        const newItemData = { productName, sellingPriceOfTotal, quantityCount, sellingPrice };
        setNewItems([...newItems, newItemData]);
        console.log(newItemData);
    }
 let handleSaveItemOnclick = () => {
        if (sellingPriceOfTotal > totalAmountIn) {
            console.log(totalAmountIn);
            console.log(sellingPrice);
            console.log("Alert is working");
           // setError(true);
            setSeverity("error")
            setMessage("Selling Price cannot be bigger than Total");
            setOpen(true)

            // setOpen(false)

        } else if (sellingPrice === 0 || productName === "") {
            console.log(sellingPrice);
            console.log(productName);
            setSeverity("error")
            //setError(true);
            setMessage("Product name and Selling price cannot be empty");
            setOpen(true)
        } else {
            handleSaveItem()
            setVisible(!visible)
            setProductName("");
            setSellingPrice(0);
            setQuantityCount(1);
        }
    }

return (
                <div>
                    <div>Items</div>
                    <ItemLists newItems={newItems} handleDelete={handleDelete}/>
                    <div className='totalItemsAdded'>
                        <p>Total</p>
                        <p>${totalSellingPrice}</p>
                    </div>
                </div>
            );
     
}

ItemLists组件

//ItemList Component
const ItemLists = (props) => {
  
    const newItems = props.newItems;
    const handleDelete =  props.handleDelete;
   
  console.log(newItems);
   
  return (
    <div>
         {newItems.map((items) => {
                        const { productName, sellingPriceOfTotal, quantityCount, sellingPrice } = items;
                        return (
                            <>
                                <div className='itemsAdded'>
                                    <div className='eachItemAdded'><div>{productName}</div>
                                        <div>{sellingPriceOfTotal} = {sellingPrice} x {quantityCount}</div>
                                    </div>
                                    <div className='deleteEditFont'><FontAwesomeIcon icon={faTrashCan} onClick={() => handleDelete(items)} /></div>

                                </div>
                            </>
                        );
                    })}
    </div>
  )
}

export default ItemLists

App组件

//App.js Component
const App = () => {
  const [newItems, setNewItems] = useState([]);
 // localStorage.setItem("newIt", JSON.stringify(newItems));

    console.log(newItems);
  return (
    <>
     <Router>
      <Routes>
        <Route path='/' exact element={<Home newItems = {newItems} setNewItems={setNewItems}/>} />
        <Route path='/moneyIn' element={<MoneyIn newItems = {newItems} setNewItems={setNewItems}/>} />
      </Routes>
     </Router>
    </>
  )
}

export default App

Home组件

//Home Component
const Home = ({newItems, setNewItems}) => {
  return (
    <>
    <div className='allBodyCards'>
   <Balances/>
   <div className='transactions'>
   <DailyTransactions />
   <MoneyInOutDetails newItems={newItems} setNewItems={setNewItems}/>
   </div>
   </div>
   </>
  )
}

export default Home

MoneyInOutDetails组件

//MoneyInOutDetails Component Where am running the map to list items in JSX
const MoneyInOutDetails = ({newItems, setNewItems}) => {
     console.log(newItems);
    newItems.map((items) => {
        const { productName, sellingPriceOfTotal} = items;
        return (
       <div className='moneyInOutWrapper'>
            <div>{productName}</div>
            <div className='amountAndIcons'>
                <div className='amountInOut'>${sellingPriceOfTotal}</div>
                <div className='deleteEditIcons'>
                    <FontAwesomeIcon icon={faPenToSquare} />
                    <FontAwesomeIcon icon={faTrashCan} />
                </div>
            </div>
        </div>
    ) })
}

export default MoneyInOutDetails

问题原因与解决办法

1. MoneyInOutDetails组件未返回渲染结果

该组件中newItems.map()执行后没有被返回,导致组件无内容输出;同时如果newItems意外变为undefined,会直接触发“无法读取map属性”的错误。

修复代码:

const MoneyInOutDetails = ({newItems, setNewItems}) => {
     console.log(newItems);
    // 必须返回map结果,且给列表项加唯一key
    return (newItems || []).map((items) => {
        const { productName, sellingPriceOfTotal} = items;
        return (
       <div className='moneyInOutWrapper' key={productName}>
            <div>{productName}</div>
            <div className='amountAndIcons'>
                <div className='amountInOut'>${sellingPriceOfTotal}</div>
                <div className='deleteEditIcons'>
                    <FontAwesomeIcon icon={faPenToSquare} />
                    <FontAwesomeIcon icon={faTrashCan} />
                </div>
            </div>
        </div>
    ) })
}
  • 用(newItems || [])确保即使props传递异常,也能以空数组执行map
  • 给每个列表项添加唯一key属性,避免React渲染警告

2. 页面刷新导致状态丢失

当前newItems仅存在于内存状态中,页面刷新后会重置为空数组。如果需要持久化数据,可在App组件中同步到localStorage:

修改App组件:

const App = () => {
  // 初始化时从localStorage读取数据
  const [newItems, setNewItems] = useState(() => {
    const saved = localStorage.getItem("newItems");
    return saved ? JSON.parse(saved) : [];
  });

  // 状态变化时自动保存到localStorage
  useEffect(() => {
    localStorage.setItem("newItems", JSON.stringify(newItems));
  }, [newItems]);

  console.log(newItems);
  return (
    <>
     <Router>
      <Routes>
        <Route path='/' exact element={<Home newItems = {newItems} setNewItems={setNewItems}/>} />
        <Route path='/moneyIn' element={<MoneyIn newItems = {newItems} setNewItems={setNewItems}/>} />
      </Routes>
     </Router>
    </>
  )
}

3. 实现方式可行性

你当前以App组件作为顶层状态容器,通过props向下传递状态的方式完全可行,是小型React应用中常用的状态管理方案。如果后续应用复杂度提升,可考虑使用Context API或Redux替代props层层传递的模式。


内容的提问来源于stack exchange,提问作者Aham_Uzoma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 20:27:02