@
@
@Predaytor2020-04-13 20:35:44
React
@Predaytor, 2020-04-13 20:35:44

How to use and update data from context in different components?

The data (lists) is used in Lists, they need to be updated in another component on an event. A number of problems arise:
In order to fetch, now you need to add the dispatch of the reducer to the useEffect dependency list, how to get rid of the rerender, but write the data to the context?
How to use data separately from the state object? It is redundant to write state.lists several times.
There is a setWrapped method, it uses the same data, now I can move it to the child List without passing props, since I have access to the context instead of the local useState?

Lists:

import React, { useEffect, useContext } from "react";
import { getAllLists, getAllNotes } from '../api';

import { StoreContext } from '../store';

import { List } from "./List";

export const Lists = () => {
  const { state, dispatch } = useContext(StoreContext);

  useEffect(() => {
    const fetchLists = async () => {
      const data = await getAllLists();
      dispatch({ type: 'SET_LISTS', payload: data });
    };

    fetchLists();
  }, [dispatch]);

  const setWrapped = id => {
    const data = [...state.lists];
    const idx = data.findIndex(i => i.id === id);
    data[idx].wrapped = !data[idx].wrapped;
    dispatch({ type: 'SET_LISTS', payload: data });
  };

  return (
    <section className="lists">
      <>
        {state.lists.map(list => (
          <List key={list.id} list={list} setWrapped={setWrapped}>{...}</List>
        ))}
      </>
    </section>
  );
}


ActionSidebar, which should update the state (when clicked, change the wrapped property to true and vice versa). The wrapped property is stored in the database and can be different for each List.
import React, { useContext } from 'react';
import { StoreContext } from '../store';

export const ActionSidebar = () => {
  const { state, dispatch } = useContext(StoreContext);

  const wrapListsHandler = () => {
    dispatch({type: 'SET_WRAP_ALL_LISTS', payload: !state.wrapAllLists});

    let data = [...state.lists];

    if (state.wrapAllLists) {
      data = data.map(i => {
        return {
          ...i,
          wrapped: false
        }
      });
    }
    else {
      data = data.map(i => {
        return {
          ...i,
          wrapped: true
        }
      });
    }
    dispatch({type: 'SET_LISTS', payload: data});
  };

  return (
    <aside className="action-sidebar">
      <button onClick={wrapListsHandler} />
    </aside>
  );
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
P
Predator, 2020-04-14
_

As far as I understand React guarantees that dispatch will only update when its type action changes. Therefore, the dispatch dependency in useEffect does not trigger the rerender.
To store a variable from the context in the component, I did this:const { lists } = state;

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question