简体   繁体   中英

How to set the active element in a list using javascript and react?

i have a list of items and clicking on one item1 should make the addbutton in it active (add backgroundcolor red) and clicking on other item say item2 should make addbutton in it active(add background color red) and item1 inactive.

below is my code,

function Parent () {
    return (
        <AddButton />//used here not considering about active index
        <List items={items}/>
    );
}
        
function List({items}: Props) {
    return (
        {Items.map((item: any) => {
            return(
                <Card>
                    <Header> title</Header>
                    <AddButton /> //want to make this active meaning add backgroundcolor red
                </Card>
            )
        }
    )
}

const useDrawing = (item) => {
    const [isToolActive, setIsToolActive] = React.useState(false);
    const [saveableDrawing, setSaveableDrawing,
  ] = React.useState<google.maps.Drawing | null>(null);
    const isDrawing = isToolActive || saveableDrawing;
    const toggleDrawing = React.useCallback(async () => {
        if (isDrawing) {
            cancelDrawing(); //this will set isToolActive to false
        } else {
            setIsToolActive(true);
        }
    }, [isDrawing, cancelDrawing]);
    return {toggleDrawing, isDrawing};
}

function AddButton ({item}: Props) {
    const {isDrawing, toggleDrawing} = useDrawing(item);
    return (
        <IconButton
            onClick={toggleDrawing}
            active={isDrawing}
        />
    );
}

function IconButton ({active}: Props) {
    return (
        <wrapper $active={active}>
    );
}

const Wrapper = styled.button<{
    $active: boolean;
}>`

    ${props =>
        props.$active &&
            css`
                background-color: red;
            `}
 `;

the above code works. but the problem is clicking one item say item1 in list add background color red to add button. and if user clicks another item say item2 in list then it also adds background color red to add button for item2.

i expect when user clicks item2 then item1 addbutton should not have background color red. only most recently clicked item in the list add button should have background color as red.

how can i fix my above code. could someone help me with this. thanks.

EDIT

I have tried something like this....

function List() {
    const [activeIndex, setActiveIndex] = React.useState(null);
    const handleClick = (itemId: any) => {
         setActiveIndex(itemId);
    }
    return (
        {Items.map((item: any, index: number) => {
            return(
                <Card>
                    <Header> title</Header>
                    <AddButton handleClick={handleClick}  isActive={activeIndex === index} /> //want to make this active meaning add backgroundcolor red
                </Card>
            )
        }
    )
}


function AddButton ({item,index, handleClick, isActive}: Props) {
    const {isDrawing, toggleDrawing} = useDrawing(item);
    const anotherClick = ()  = >{
        handleClick(index);
        toggleDrawing();
    }
    return (
        <IconButton
            onClick={AnotherClick}
            active={isDrawing && isActive}
        />
    );
}

this works but when user clicks the item1 the item1 add button has background color and when item2 is clicked twice only the addbutton for item2 has background color.

i am not sure what is causing this. could someone help me fix this. thanks.

You have to move the logic for activating buttons one level up, to List component. There, you have to keep track of which button is currently active:

 function List() { const [activeButtonIndex, setActiveIndex] = React.useState(); return ( {Items.map((item: any, index: number) => { return( <Card> <Header> title</Header> <AddButton isToolActive={activeButtonIndex === index} index={index} setActiveIndex={setActiveIndex} /> //want to make this active meaning add backgroundcolor red </Card> ) } ) } const useDrawing = (item, index, isToolActive, setActiveIndex) => { const isDrawing = isToolActive; toggleDrawing= () => { if (isToolActive) { setActiveIndex(undefined); } setActiveIndex(index); } return {toggleDrawing, isDrawing}; } function AddButton ({item, index, isActive, setActiveIndex}: Props) { const {isDrawing, toggleDrawing} = useDrawing(item, index, isToolActive, setActiveIndex); return ( <IconButton onClick={toggleDrawing} active={isDrawing} /> ); } function IconButton ({active}: Props) { return ( <wrapper $active={active}> ); } const Wrapper = styled.button<{ $active: boolean; }>` ${props => props.$active && css` background-color: red; `} `;

You can set index of clicked item into the state and check from the state if the index of list item same as stored in the state make it active.

 function List() {
    const [activeIndex, setActiveIndex] = React.useState(null);
    const handleClick = (key: number) => {
         setActiveIndex(key);
    }
    return (
        {Items.map((item: any, key: number) => {
            return(
                <Card>
                    <Header> title</Header>
                    <AddButton handleClick={() => handleClick(key)} **isActive={key ==activeIndex}** />
                </Card>
            )
        }
    )
}


function AddButton ({ handleClick, isActive}: Props) {
    const anotherClick = ()  = >{
        handleClick();
    }
    return (
        <IconButton
            onClick={AnotherClick}
            active={isActive}
        />
    );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM