Javascript 两个功能组件之间的双向通信

Javascript 两个功能组件之间的双向通信,javascript,reactjs,frontend,web-frontend,Javascript,Reactjs,Frontend,Web Frontend,我在React中内置了两个功能组件,一个是Item组件——它包含一些关于物品的数据,可选的图形、文本数据和价格信息。底部有一个按钮,允许您选择此特定项目。它还将当前所选项目的ID信息保存在道具中——这就是我计划解决此问题的方法 我的第二个组件是一个ItemList——它基本上保存了一个上述项目的列表——加上它对所有项目进行排序,并且必须保留关于当前选择哪个组件的信息——选择的组件基本上看起来不同——一些东西,比如边框框和按钮的颜色通过CSS进行切换 我的实现逻辑是这样的——当用户单击某个特定项的

我在React中内置了两个功能组件,一个是Item组件——它包含一些关于物品的数据,可选的图形、文本数据和价格信息。底部有一个按钮,允许您选择此特定项目。它还将当前所选项目的ID信息保存在道具中——这就是我计划解决此问题的方法

我的第二个组件是一个ItemList——它基本上保存了一个上述项目的列表——加上它对所有项目进行排序,并且必须保留关于当前选择哪个组件的信息——选择的组件基本上看起来不同——一些东西,比如边框框和按钮的颜色通过CSS进行切换

我的实现逻辑是这样的——当用户单击某个特定项的“选择”按钮时,该项应该改变它的外观(除非它已经被选中,然后什么也不做),然后以某种方式将信息传播到ItemList上,这样它就可以“禁用”以前选择的组件。只能选择一个项目,一旦用户决定选择另一个项目,以前选择的项目应更改其状态并返回未选择的标准图形样式

我遇到过一个在ItemList组件中包含状态的解决方案,并通过道具将一个函数传递到Item中,但这并不能解决第二部分-ItemList需要获取有关更改的信息,以便它可以根据实际状态重新提交所有组件。我应该深入React API的哪一部分来解决这个问题

以下是我的组件的代码:

项目

界面道具{
接收对象:要显示的项目;
selectedItemId:string;
onClick?:()=>void;
}
导出默认功能项(道具:道具){
const{name,description,price}=props.receivedObject;
const imageUrl=props.receivedObject?.media?.mainImage?.small?.url;
常数priceComponent=;
const[isItemSelected,setSelection]=useState(props.selectedItemId==props.receivedObject.id);
const onClick=props.onClick | |(()=>{
setSelection(!isItemSelected)
});
返回(
//展示的东西放在这里
//这是一个按钮,它应该以某种方式向上发送有关新选定项目的信息
{isItemSelected?“SELECTED”:“SELECT”}
)
};
项目列表

界面道具{
packageItems:数组
}
导出默认函数项列表(道具:道具){
const itemsToDisplay=props.packageItems;
itemsToDisplay.sort((a,b)=>
a、 price.finalPrice-b.price.finalPrice
);
让selectedItemId=items显示[0].id;
const[currentlySelectedItem,changeCurrentlySelectedItem]=useState(selectedItemId);
const setSelectedItemFunc=()=>{
/*此函数应作为道具传递,但它只能
*有一个“this”指代,意思是“this”指的是单数项`
*如何使其更改'ItemList'组件中的状态?
*/
log(“列表中定义的函数”);
};
返回(
{itemsToDisplay.slice(1).map((项)=>(
))}
);
}
在React中,因此最好将状态数据保存在呈现表示组件的有状态组件中

函数列表项({说明,价格,已选,已选}){
返回(
  • {说明} ${price} {已选择?“已选择”:“选择”}
  • ); } 函数列表({children}){ return
      {children}
    ; } 函数内容({items}){ const[selectedId,setSelectedId]=React.useState(“”); const createClickHandler=React.useCallback( id=>()=>设置所选id(id), [] ); 返回( {项目 .sort(({price:a},{price:b})=>a-b) .map(项目=>( ))} ); } 函数App(){ 常数项=[ {id:1,描述:“#1描述”,价格:17}, {id:2,描述:“#2描述”,价格:13}, {id:3,描述:“#3描述”,价格:19} ]; 返回( ); } ReactDOM.render( , document.getElementById(“根”) );
    .App{
    字体系列:无衬线;
    }
    .List>.ListItem{
    保证金:5px;
    }
    .ListItem{
    填充:10px;
    }
    .ListItem>*{
    利润率:0.5px;
    }
    .ListItem:悬停{
    背景颜色:浅灰色;
    }
    .ListItem.selected{
    背景色:暗灰色;
    }

    谢谢,这是一个非常简单的答案,为了解决这个问题,我正在深入研究上下文和一些更高级的React概念,big up:)
    interface Props {
        receivedObject: itemToDisplay;
        selectedItemId: string;
        onClick?: () => void;
    }
    
    export default function Item(props: Props) {
        const {name, description, price} = props.receivedObject;
        const imageUrl = props.receivedObject?.media?.mainImage?.small?.url;
        const priceComponent = <Price price={price}/>;
        const [isItemSelected, setSelection] = useState(props.selectedItemId == props.receivedObject.id);
        const onClick = props.onClick || (() => {
            setSelection(!isItemSelected)
        });
        return (
            <>
                <div className="theDataHolderContainer">
                // displayed stuff goes here
                    <div className="pickButtonContainer">
                        // that's the button which should somehow send info "upwards" about the new selected item
                        <Button outline={isItemSelected} color="danger" onClick={onClick}>{isItemSelected ? "SELECTED" : "SELECT"}</Button>
                    </div>
    
                </div>
            </>)
    };
    
    interface Props {
        packageItems: Array<itemToDisplay>
    }
    
    export default function ItemList(props: Props) {
        const itemsToDisplay = props.packageItems;
        itemsToDisplay.sort((a, b) =>
            a.price.finalPrice - b.price.finalPrice
        );
        let selectedItemId = itemsToDisplay[0].id;
        const [currentlySelectedItem, changeCurrentlySelectedItem] = useState(selectedItemId);
    
        const setSelectedItemFunc = () => { 
            /* this function should be passed down as a prop, however it can only 
             * have one `this` reference, meaning that `this` will refer to singular `Item`
             * how do I make it change state in the `ItemList` component?
             */
        
            console.log('function defined in list');
        };
        return(
            <div className="packageNameList">
                <Item
                    key={itemsToDisplay[0].id}
                    receivedObject={itemsToDisplay[0]}
                    onClick={setSelectedItemFunc}
                />
    
                {itemsToDisplay.slice(1).map((item) => (
                    <Item
                        key={item.id}
                        receivedObject={item}
                        onClick={setSelectedItemFunc}
                    />
                    ))}
            </div>
        );
    }