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

React组件间共享goodData状态问题求助(含同/跨文件场景)

问题分析与解决方案

你的代码里有两个关键错误导致use-between没生效:

  1. use-between用法错误:它需要传入自定义Hook,而不是组件本身。你把AddProduct组件传给了useBetween,完全不符合API要求。
  2. ActionBox组件props接收错误:React组件的props是单个对象参数,你写成了多个独立参数,导致无法正确获取传入的值。

同一文件下的修复方案

先把状态逻辑抽成自定义Hook,再用use-between共享:

import React, { useState, useEffect } from 'react'
import {IoMdAdd, IoIosListBox} from 'react-icons/io'
import {MdClear} from 'react-icons/md'
import {AiOutlineMinusSquare} from 'react-icons/ai'
import {AiFillCloseCircle} from 'react-icons/ai'
import {useBetween} from 'use-between'
import { goods } from '../dataArray'

// 1. 抽离共享状态到自定义Hook
const useGoodDataHook = () => {
    const [presentDate, setPresentDate] = useState('')
    const [goodData, setGoodData] = useState({modDate: '',product: '', quantity: '', unitPrice: '', totPrice: ''})
    const [dropStockList, setDropStockList] = useState(true)
    const [stock, setStock] = useState([])
    const [shop, setShop] = useState([])
    const [display, setDisplay]  = useState(true)
    const [actionBtn, setActionBtn] = useState(true)

    useEffect(()=>{
        let date = new Date()
        let day = date.getUTCDay()
        let month = date.getUTCMonth()
        let year = date.getUTCFullYear()
        let newDate = day+'/'+month+'/'+year
        setPresentDate(newDate)
        let list;
        if (localStorage.getItem('shopDB') !== null) {
            list = JSON.parse(localStorage.getItem('shopDB')).warehouse
            setStock(list)
        }
    },[])

    function handleNewStock(data) {
        let shopDB;
        if (localStorage.getItem('shopDB') !== null) {
            shopDB = JSON.parse(localStorage.getItem('shopDB'))
            shopDB.warehouse.push(data)
        } else {
            shopDB = { warehouse: [data] }
        }
        localStorage.setItem('shopDB', JSON.stringify(shopDB))
    }

    function handleChange(e) {
        let name = e.target.name
        let value = e.target.value
        setGoodData({...goodData, [name]:value})
    }
    
    function handleSubmit(e) {
        e.preventDefault()

        if (goodData.product && goodData.quantity && goodData.unitPrice ) {
            const newGoodData = {
                ...goodData,
                totPrice: goodData.quantity * goodData.unitPrice,
                modDate: presentDate
            }
            setStock([...stock, newGoodData]) 
            handleNewStock(newGoodData)
            setGoodData({modDate: '', product:'', quantity: '', totPrice: '', unitPrice: ''})
        } else {
            // highlight unfilled field
        }
    }

    function handleCheck() {
        setDisplay(!display)
    }
    
    function handleStockList() {
        setDropStockList(!dropStockList)
    }

    return {
        presentDate,
        goodData,
        setGoodData,
        dropStockList,
        stock,
        display,
        actionBtn,
        handleChange,
        handleSubmit,
        handleCheck,
        handleStockList
    }
}

// 2. 用use-between包装自定义Hook,创建共享状态Hook
const useSharedState = () => useBetween(useGoodDataHook)

const AddProduct = () => {
    // 3. 在组件中使用共享状态
    const {
        presentDate,
        goodData,
        dropStockList,
        stock,
        display,
        actionBtn,
        handleChange,
        handleSubmit,
        handleCheck,
        handleStockList
    } = useSharedState()

    function handleBlurClose() {
        // setDisplay(false)
    }

    return (
    <>
    {display && <section className="add-stock-cont" >
        <div className="addition" onBlur={handleBlurClose}>
            <div className="nav">
                <section className="title">
                    <h2>Add New Product</h2>
                </section>
                <span id="close-icon" onClick={handleCheck}>
                    <AiFillCloseCircle />
                </span>
            </div>

            {display && 
            <form className="add-area">
                <section className="top">
                    <section className = "product form-group" >
                        <label htmlFor = "product" > Product </label> 
                        <input type = "text"
                        name = "product"
                        id = "product"
                        placeholder = 'Semovita...'
                        onChange = { handleChange }
                        value = { goodData.product }/> 
                    </section>

                    <section className = "quantity form-group" >
                        <label htmlFor = "quantity" > Quantity </label> 
                        <input type = "number"
                        name = "quantity"
                        id = "quantity"
                        placeholder = '0'
                        onChange = { handleChange }
                        value = { goodData.quantity }/> 
                    </section>

                    
                    <section className = "unitPrice form-group" >
                        <label htmlFor = "unitPrice" > Unit Price </label> 
                        <input type = "number"
                        name = "unitPrice"
                        id = "unitPrice"
                        placeholder = '0'
                        onChange = { handleChange }
                        value = { goodData.unitPrice }/> 
                    </section>

                    <article className="totPrice">
                        <h4>{goodData.totPrice}</h4>
                    </article>

                </section>
                <section className="buttons">
                    {actionBtn &&<button className="unClear-btn add-btn" type='submit' onClick={handleSubmit}>
                        <span id='icon'><IoMdAdd /> </span> Add
                    </button>}
                    {!actionBtn && <button className="warning-color unClear-btn" id="update-btn">Update</button>}
                    <button className="unClear-btn clear-btn"><span id="icon"><MdClear /> </span> Clear</button>
                        {!actionBtn && <button className="unClear-btn " id="delete-btn">Delete</button>}
                </section>
            </form>}
            <section className="stock-list">
                <div className="menu-bar" onClick={handleStockList}>
                    {dropStockList ?  <span id="icon"><AiOutlineMinusSquare /> </span> : <span id="icon"><IoIosListBox/> </span>  }
                </div>
                {dropStockList &&  
                <section className="table-holder">
                    <table>
                        <thead>
                            <tr>
                                <th>Date Mod.</th>
                                <th>Product</th>
                                <th>Quantity</th>
                                <th>Unit Price</th>
                                <th>Total Price</th>
                                <th>Actions</th>
                            </tr>
                        </thead>
                        <tbody>
                            
                                {stock.map((data, index)=>{
                                    const {product, quantity, unitPrice, totPrice, modDate} = data

                                    return(
                                        <tr key={index}>
                                            <td>{modDate}</td>
                                            <td>{product}</td>
                                            <td>{quantity}</td>
                                            <td>{unitPrice}</td>
                                            <td>{totPrice}</td>
                                            <td><ActionBox index={index} product={data.product} quantity={data.quantity} unitPrice={data.unitPrice} totPrice={data.totPrice}/> </td>
                                        </tr>
                                    )
                                })}
                        </tbody>
                    </table>
                
                </section>
                }
            </section>
        </div> 
    </section>}
   </> )
}

const ActionBox = ({index, unitPrice, product, quantity, totPrice})=>{
    const [dropDown,  setDropDown] = useState(false)
    // 4. 在子组件中获取共享状态
    const {goodData} = useSharedState();

    function handleEdit() {
        console.log(index);
        console.log('printing...', goodData);
        let shopDB;
        if (localStorage.getItem('shopDB') !== null) {
            shopDB = JSON.parse(localStorage.getItem('shopDB')).warehouse
            console.log('the necessary info',shopDB.at(index));
        } else {
            console.log('You are on your own lol...');
        }
    }

    return(
        <button className="unClear-btn" onClick={handleEdit}>
            action
        </button>
    )
}

export default AddProduct

不同文件下的实现方式

把共享状态Hook单独放在一个文件里,比如src/hooks/useSharedGoodData.js:

import { useState, useEffect } from 'react'
import {useBetween} from 'use-between'

const useGoodDataHook = () => {
    const [presentDate, setPresentDate] = useState('')
    const [goodData, setGoodData] = useState({modDate: '',product: '', quantity: '', unitPrice: '', totPrice: ''})
    const [dropStockList, setDropStockList] = useState(true)
    const [stock, setStock] = useState([])
    const [shop, setShop] = useState([])
    const [display, setDisplay]  = useState(true)
    const [actionBtn, setActionBtn] = useState(true)

    useEffect(()=>{
        let date = new Date()
        let day = date.getUTCDay()
        let month = date.getUTCMonth()
        let year = date.getUTCFullYear()
        let newDate = day+'/'+month+'/'+year
        setPresentDate(newDate)
        let list;
        if (localStorage.getItem('shopDB') !== null) {
            list = JSON.parse(localStorage.getItem('shopDB')).warehouse
            setStock(list)
        }
    },[])

    function handleNewStock(data) {
        let shopDB;
        if (localStorage.getItem('shopDB') !== null) {
            shopDB = JSON.parse(localStorage.getItem('shopDB'))
            shopDB.warehouse.push(data)
        } else {
            shopDB = { warehouse: [data] }
        }
        localStorage.setItem('shopDB', JSON.stringify(shopDB))
    }

    function handleChange(e) {
        let name = e.target.name
        let value = e.target.value
        setGoodData({...goodData, [name]:value})
    }
    
    function handleSubmit(e) {
        e.preventDefault()

        if (goodData.product && goodData.quantity && goodData.unitPrice ) {
            const newGoodData = {
                ...goodData,
                totPrice: goodData.quantity * goodData.unitPrice,
                modDate: presentDate
            }
            setStock([...stock, newGoodData]) 
            handleNewStock(newGoodData)
            setGoodData({modDate: '', product:'', quantity: '', totPrice: '', unitPrice: ''})
        } else {
            // highlight unfilled field
        }
    }

    function handleCheck() {
        setDisplay(!display)
    }
    
    function handleStockList() {
        setDropStockList(!dropStockList)
    }

    return {
        presentDate,
        goodData,
        setGoodData,
        dropStockList,
        stock,
        display,
        actionBtn,
        handleChange,
        handleSubmit,
        handleCheck,
        handleStockList
    }
}

export const useSharedState = () => useBetween(useGoodDataHook)

然后在AddProduct.jsx里导入:

import { useSharedState } from './hooks/useSharedGoodData'
// ... 其他导入

const AddProduct = () => {
    const { ... } = useSharedState()
    // 组件逻辑不变
}

在ActionBox.jsx里单独导出并导入:

import { useState } from 'react'
import { useSharedState } from './hooks/useSharedGoodData'

const ActionBox = ({index, unitPrice, product, quantity, totPrice})=>{
    const [dropDown,  setDropDown] = useState(false)
    const {goodData} = useSharedState();

    function handleEdit() {
        // ... 逻辑不变
    }

    return(
        <button className="unClear-btn" onClick={handleEdit}>
            action
        </button>
    )
}

export default ActionBox

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:15:33