Javascript 两个功能组件之间的双向通信
我在React中内置了两个功能组件,一个是Item组件——它包含一些关于物品的数据,可选的图形、文本数据和价格信息。底部有一个按钮,允许您选择此特定项目。它还将当前所选项目的ID信息保存在道具中——这就是我计划解决此问题的方法 我的第二个组件是一个ItemList——它基本上保存了一个上述项目的列表——加上它对所有项目进行排序,并且必须保留关于当前选择哪个组件的信息——选择的组件基本上看起来不同——一些东西,比如边框框和按钮的颜色通过CSS进行切换 我的实现逻辑是这样的——当用户单击某个特定项的“选择”按钮时,该项应该改变它的外观(除非它已经被选中,然后什么也不做),然后以某种方式将信息传播到ItemList上,这样它就可以“禁用”以前选择的组件。只能选择一个项目,一旦用户决定选择另一个项目,以前选择的项目应更改其状态并返回未选择的标准图形样式 我遇到过一个在ItemList组件中包含状态的解决方案,并通过道具将一个函数传递到Item中,但这并不能解决第二部分-ItemList需要获取有关更改的信息,以便它可以根据实际状态重新提交所有组件。我应该深入React API的哪一部分来解决这个问题 以下是我的组件的代码: 项目Javascript 两个功能组件之间的双向通信,javascript,reactjs,frontend,web-frontend,Javascript,Reactjs,Frontend,Web Frontend,我在React中内置了两个功能组件,一个是Item组件——它包含一些关于物品的数据,可选的图形、文本数据和价格信息。底部有一个按钮,允许您选择此特定项目。它还将当前所选项目的ID信息保存在道具中——这就是我计划解决此问题的方法 我的第二个组件是一个ItemList——它基本上保存了一个上述项目的列表——加上它对所有项目进行排序,并且必须保留关于当前选择哪个组件的信息——选择的组件基本上看起来不同——一些东西,比如边框框和按钮的颜色通过CSS进行切换 我的实现逻辑是这样的——当用户单击某个特定项的
界面道具{
接收对象:要显示的项目;
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>
);
}