簡體   English   中英

兩個功能性 React JS 組件之間的雙向通信

[英]Two way communication between two functional React JS components

我在 React 中構建了兩個功能組件,一個是Item組件——它包含一些關於東西的數據,帶有可選的圖形、一些文本數據和價格信息。 在底部有一個按鈕,可以讓你 select 這個特定項目。 它還在其道具中保存有關當前所選項目ID 的信息——這就是我計划解決此問題的方式。

我的第二個組件是ItemList - 它基本上包含一個前面提到的項目列表 - 加上它對所有項目進行排序,並且必須保留有關當前選擇哪個組件的信息 - 所選組件基本上看起來不同 - 一些東西,比如邊框框和按鈕的顏色通過 CSS 切換。

我的實現邏輯是這樣的——當用戶點擊特定項目的“選擇”按鈕時,項目應該改變它的外觀(除非它已經被選中,然后什么都不做),然后以某種方式將信息傳播到ItemList上,所以它可以“禁用”先前選擇的組件。 只能選擇一個Item ,一旦用戶決定 select 另一個,之前選擇的應該將其 state 和 go 更改回未選擇的標准圖形樣式。

我在ItemList組件中遇到了 state 的解決方案,並通過道具將 function 通過道具傳遞給Item ,但這並不能解決第二部分 - ItemList需要獲取有關更改的信息,因此它可以根據實際 state。 我應該深入研究 React API 的哪一部分來解決這個問題?

這是我的組件的代碼:

物品

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>
    );
}

在 React 中, 數據是向下流動的,因此您最好將 state 數據保存在呈現表示組件的有狀態組件中。

 function ListItem({ description, price, selected, select }) { return ( <li className={"ListItem" + (selected? " selected": "")}> <span>{description}</span> <span>${price}</span> <button onClick={select}>{selected? "Selected": "Select"}</button> </li> ); } function List({ children }) { return <ul className="List">{children}</ul>; } function Content({ items }) { const [selectedId, setSelectedId] = React.useState(""); const createClickHandler = React.useCallback( id => () => setSelectedId(id), [] ); return ( <List> {items.sort(({ price: a }, { price: b }) => a - b).map(item => ( <ListItem key={item.id} {...item} selected={item.id === selectedId} select={createClickHandler(item.id)} /> ))} </List> ); } function App() { const items = [ { id: 1, description: "#1 Description", price: 17 }, { id: 2, description: "#2 Description", price: 13 }, { id: 3, description: "#3 Description", price: 19 } ]; return ( <div className="App"> <Content items={items} /> </div> ); } ReactDOM.render( <App />, document.getElementById("root") );
 .App { font-family: sans-serif; }.List >.ListItem { margin: 5px; }.ListItem { padding: 10px; }.ListItem > * { margin: 0 5px; }.ListItem:hover { background-color: lightgray; }.ListItem.selected { background-color: darkgray; }
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM