简体   繁体   中英

"Cannot read property 'map' of undefined" when utilizing .map to create various JSX components?

I am having a bit of an issue when attempting to.map a React state variable into various JSX elements. I have noticed that the state variable I am storing the array within is not undefined, as "console.log-ing" the variable appears to hold the information I need it to. The error according to my React Development Page mentions the error starts at line 43 Here is my code for the main Dashboard.js I am utilizing the.map function within to create new list items.

import React, {useState} from 'react';
import {generateId} from '../../Utilities/generateId.js';
import {expirationTime} from '../../Utilities/expirationTime.js';
import {Form} from '../Form/Form.js';
import {Thought} from '../Thought/Thought.js';

export function Dashboard() {
    // Sets up sample message when site first loads up; eventually disappears after 15s
    // generateId adheres an id number starting at 0, to each thought to easily identify each thought
    // expirationTime sets the automatic removal of the "thought" 15 seconds away from current time
    const [thoughts, setThoughts] = useState([
        {
        id: generateId(),
        text: "Add your thoughts, don't be shy!",
        expires: expirationTime(),
        }, 
        {
        id: generateId(),
        text: 'They disappear after 15 seconds!',
        expires: expirationTime(), 
        }
    ]);

    //adds new thought object to array lists out all collective thoughts in thoughts array
    const addThought = (thought) => {
        setThoughts((prev) => [thought, ...prev]);
    };

    const removeThought = (thoughtID) => {
        //reuses state and uses filter function to cycle through each object in the thoughts array,
        // and remove the thought whose ID matches the one that was selected(clicked) on
        setThoughts((prev) => {
            prev.filter((thought) => thought.id !== thoughtID)
        });
    };

    return (
        <div>
            <h1>Thought Machine</h1>
            <h3>Welcome! This is an open space for any of your thoughts.</h3>
            <h2>Thanks for visiting!</h2>
            <Form addThought={addThought} />
            <ul className='thoughts'>
                {thoughts.map( thought => 
                    (<Thought key={thought.id} thought={thought} removeThought={removeThought} />) 
                    // thought.text
                )}
            </ul>
        </div>
    )
};

Aside from the main code here, here is my code for Thought.js, where I pass in my props for the "thoughts" I am attempting to individually list out. I do not believe there is any issue with my code here, yet I am posting it just in case.

Thought.js:

import React, {useEffect} from 'react';

export function Thought(props) {
    const {thought, removeThought} = props;

    useEffect(() => {
        const timeRemaining = thought.expirationTime - Date.now();

        const timeout = setTimeout(() => {
            removeThought(thought.id)
        }, timeRemaining);

        return () => {
            clearTimeout(timeout);
        }
    }, [thought]);

    const handleRemoveClick = () => {
        removeThought(thought.id);
    };

    return (
        <li className='Thought'>
            <button className='remove-button' onClick={handleRemoveClick}>&times;</button>
            <p className='text' >{thought.text}</p>
        </li>
    )
};

I also do not believe that there is any issue with my code for the Form, yet here is that following code just in case my judgment is incorrect.

Form.js:

import React, {useState} from 'react';
import {generateId} from '../../Utilities/generateId.js';
import {expirationTime} from '../../Utilities/expirationTime.js';

import './Form.css';

export function Form(props) {
    const [text, setText] = useState('');

    //this function is called everytime the text value in the entry box is changed... adjusts state value of text
    const handleTextChange = (event) => {
        setText(event.target.value);
    };

    const handleSubmit = (event) => {
        event.preventDefault();

        //sets object for new thought and fills in new message; new generated ID and new time 15 seconds ahead of current time
        const thought = {
            id: generateId(),
            text: text,
            expiresAt: expirationTime(),
        };
        
        // checks if text has any text within it, then submits the new 'thought' to props.addThought
        if (text.length > 0) {
            props.addThought(thought);
            // sets text state back to blank after submitting new thought
            setText('');
        }
    }

    return (
        <form onSubmit={handleSubmit} className='Form'>
            <input value={text} onChange={handleTextChange} type='text' placeholder="Go ahead ... there's no CIA agents here :)" />
            <input type='submit' value='add' />
        </form>
    );
};

Apologies for the convoluted-ness of the question and thanks ahead of time for any assistance!

May be you are getting an error undefined at line 43 at the time of updating because of this code

const removeThought = (thoughtID) => {
        setThoughts((prev) => {
            return prev.filter((thought) => thought.id !== thoughtID) <---- You have to return as well
        });
    };

Explanation

When you are setting state while updating , you are returning nothing , thus the state is settled to undefined and we can't map over undefined.

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