reactjstypescriptantd

Child component must to rerender the parent (collapse component) one many times


It is need that when the button is pressed, it immediately turns red, and in the second tab the value changes to true. To do this, you need to rerender the parent component. The option that is used works only once, but it should work for everyone.

import React from 'react';
import type { CollapseProps } from 'antd';
import { Collapse, Button, Space } from 'antd';  
import { useState } from "react";



let value1 = false;
let value2 = false;
let value3 = false;


const Element1 = (props: any) => {
    const handleClick = (key: number) => {
        if (key == 1) {
            value1 = true
        }
        else if (key == 2) {
            value2 = true
        }
        else {
            value3 = true
        }
        props.callBack(true);
    }

    return (
        <div>
            <div>
                <Space >
                    <Button
                        onClick={() => handleClick(1)}
                        color={!value1 ? "primary" : "danger"}
                        variant="solid"
                    >Button1
                </Button>
                    <Button
                        onClick={() => handleClick(2)}
                        color={!value2 ? "primary" : "danger"}
                        variant="solid"
                    >Button2
                </Button>
                    <Button
                        onClick={() => handleClick(3)}
                        color={!value3 ? "primary" : "danger"}
                        variant="solid"
                    >Button3
                </Button>
                </Space>
            </div>
        </div>
    );
}

const Element2 = () => {
    return (
        <div>
            <div>
                <p>value1 <b>{value1.toString()}</b></p>
                <p>value2 <b>{value2.toString()}</b></p>
                <p>value3 <b>{value3.toString()}</b></p>
            </div>
        </div>
    );
}


const CollapseComponent: React.FC = () => {
    const [ , setReload] = useState(false);

    const items: CollapseProps['items'] = [
        {
            key: '1',
            label: 'Element1',
            children: <Element1 callBack={setReload} />
        },
        {
            key: '2',
            label: 'Element2',
            children: <Element2 />
        }
    ];


    return (
        <Collapse items={items}  />
    );
};

export default CollapseComponent;

Solution

  • The solution turned out to be very simple. A hook was added to the parent component, which was passed to the child. There it changes, which causes the parent to be rerender.

    import React from 'react';
    import type { CollapseProps } from 'antd';
    import { Collapse, Button, Space } from 'antd';
    import { useState } from "react";
    
    
    let value1 = false;
    let value2 = false;
    let value3 = false;
    
    
    
    interface Props {
        counter: number;
        setCounter: (key: number) => void;
    }
    
    
    const Element1 = ({ counter, setCounter }: Props) => {
    
        const handleClick = (key: number) => {
            if (key == 1) {
                value1 = true
                console.log('value1 ', value1.toString())
            }
            else if (key == 2) {
                value2 = true
                console.log('value2 ', value2.toString())
            }
            else {
                value3 = true
                console.log('value3 ', value3.toString())
            }
            counter++;                 // change the hook
            setCounter(counter)        // set new value
        }
    
        return (
            <div>
                <div>
                    <Space >
                        <Button
                            onClick={() => handleClick(1)}
                            color={!value1 ? "primary" : "danger"}
                            variant="solid"
                        >Button1
                        </Button>
                        <Button
                            onClick={() => handleClick(2)}
                            color={!value2 ? "primary" : "danger"}
                            variant="solid"
                        >Button2
                        </Button>
                        <Button
                            onClick={() => handleClick(3)}
                            color={!value3 ? "primary" : "danger"}
                            variant="solid"
                        >Button3
                        </Button>
                    </Space>
                </div>
            </div>
        );
    }
    
    const Element2 = () => {
        return (
            <div>
                <div>
                    <p>value1 <b>{value1.toString()}</b></p>
                    <p>value2 <b>{value2.toString()}</b></p>
                    <p>value3 <b>{value3.toString()}</b></p>
                </div>
            </div>
        );
    }
    
    
    
    const CollapseComponent: React.FC = () => {
        const [counter, setCounter] = useState<number>(0);    // new hook
    
        const items: CollapseProps['items'] = [
            {
                key: '1',
                label: 'Element1',
                // pass to child 
                children: <Element1 counter={counter} setCounter={setCounter} />
            },
            {
                key: '2',
                label: 'Element2',
                children: <Element2 />
            }
        ];
    
        return (
            <div>
                <Collapse items={items} />
            </div>            
        );
    };
    
    export default CollapseComponent;