How to create a list within a list item with React.js, useRouter and useStore?

Viewed 19

does someone have an idea for a solution to the following problem? I would be really happy for some advice!

Here are some information to help understand what I'm about to do:

  • there is a list where you can add your DIY projects
  • when you click the edit button of a project, you can add some information to every project.

Link to the project: https://diy-project-planner.vercel.app/

My problem:

  • when I write down a note within a project, it appears on every project instead of just the one I added the note to:

The Code of the edit page

    const projects = useStore(state => state.projects);
    const router = useRouter();
    const {id} = router.query;
    const entry = projects.find(entry => entry.id === String(id));
    const notes = useStore(state => state.notes);
    const addNote = useStore(state => state.addNote);
    const [note, setNote] = useState('');

    if (!entry) {
        return;
    }

    return (
        <Layout>
            <h1>{entry.name}</h1>
            <h2>Notizen</h2>
            <form
                onSubmit={event => {
                    event.preventDefault();
                    addNote(note);
                }}
            >
                <StyledInputField
                    type="text"
                    value={note}
                    onChange={event => {
                        setNote(event.target.value);
                    }}
                />
                <StyledButton type="submit">add</StyledButton>
                {notes.map(note => {
                    return <p key={note.id}>{note.name}</p>;
                })}
            </form>{' '}
        </Layout>
    );
}

The code of useStore (Global State Handling with Zustand)

const useStore = create(set => ({
    projects: [
        {name: 'Pflanzenleiter', id: nanoid(), isDone: false},
        {name: 'Bilderrahmen', id: nanoid(), isDone: false},
    ],
    addProject: name => {
        set(state => {
            return {
                projects: [...state.projects, {id: nanoid(), name, isDone: false}],
            };
        });
    },

    notes: [],
    addNote: name => {
        set(state => {
            return {
                notes: [...state.notes, {id: nanoid(), name}],
            };
        });
    },

Thanks a lot in advance for your help! :-)

1 Answers

I think your problem is that you're not specifying which entry to add the note to. When you update your note you're setting it in the notes useState hook. That's fine. However, once you've submitted your note you're calling the useStore method. This adds the note to the list of notes. This list is used for all entry items in your useStore. Instead you would want to change your state to look something like this:

projects: [
    {name: 'Pflanzenleiter', id: nanoid(), isDone: false, notes: []},
...
addNote: name => {
    set(state => {
        let entryToUpdate = state.projects.filter((p) => p.name == name);
        entryToUpdate.notes.append(note)
        return {
            notes: [...state.projects, entryToUpdate],
        };
    });
},

Not tested. The idea is that you have a single store. Don't break up notes and projects. The note needs to be attached to the project in some way. That way when you add the note it is applied the the project it was meant for instead of a global all notes that isn't attached to anything.

Related