Antoine Grenard
Antoine Grenard

Reputation: 1892

React : state is empty when trying to get it from child component

I got two react components. The first component is managing a list of the second component after making a call to my api and I tried to put a delete button to remove one component from the list.

I got a weird behavior : when I click on the remove document button the document is set to an empty array. And I got a log of an empty array for the documents.

Parent component :

export const DocumentEnvelope: React.FC<DocumentEnvelopeProps> = (props) => {
    const [documents, setDocuments] = useState([]);

    useEffect(() => {
        setDocuments([]);
        axios.get("/myurl").then(response => {
            response.data.forEach(document => {
                setDocuments((doc) => [...doc, <Document name={document.name} removeDocument={removeDocument}/>]);});
        });
    }, []);

    const removeDocument = (name) => {
        console.log(documents);
        setDocuments(documents.filter(item => item.name !== name));
    };

    return (
        <>
            {documents}
        </>
    );
};

Child component :

interface DocumentProps {
    removeDocument,
    name: string
}

export const Document: React.FC<DocumentProps> = (props) => {

    return (
        <div>
            My document
            <button onClick={() => props.removeDocument(props.name)}>
                Remove document
            </button>
        </div>
    );
};

Upvotes: 1

Views: 341

Answers (2)

Lakshya Thakur
Lakshya Thakur

Reputation: 8316

You're filtering on the documents array as if it consisted of document objects. But you have set the documents array to list of Document React Elements.

Let your documents array consist pure JS objects i.e. a document as you're getting it from response instead of React elements. Use map in JSX to loop over documents and return <Document.../> elements.

I mean like the following :-

export const DocumentEnvelope: React.FC<DocumentEnvelopeProps> = (props) => {
    const [documents, setDocuments] = useState([]);

    useEffect(() => {
        axios.get("/myurl").then(response => {
            setDocuments(response.data);
    }, []);

    const removeDocument = (name) => {
        setDocuments(documents.filter(document => document.name !== name));
    };

    return (
        <>
            {documents.map((document)=>
           <Document name={document.name} removeDocument={removeDocument}/>
)}
        </>
    );
};

Upvotes: 1

Brouwer
Brouwer

Reputation: 681

<Document name=document.name removeDocument={removeDocument}/>

This part is missing curly braces around document.name, consider using a different variable name as document is used to refer to the html document in javascript. I can also recommend storing the data in the state but not the components themselves.

Upvotes: 1

Related Questions