React Context для передачи массива

У меня есть следующий компонент входа в приложение:

  React.useEffect(() => {
    const fetchData = async () => {
      try {
        const libraries: unknown[] = await sendRequest('/libraries');
        const softwareComponents: unknown[] = await sendRequest('/softwareComponents');

        localStorage.setItem('libraries', JSON.stringify(arraySetup(libraries, 'libraries')));
        localStorage.setItem('softwareComponents', JSON.stringify(arraySetup(softwareComponents, 'software-components')));
      } catch (err) {
        console.error(err);
      }
    };
    isAuthenticated() && fetchData();
  }, []);

Я извлекаю массивы из двух конечных точек, а затем устанавливаю результат в локальное хранилище, чтобы я мог читать его в других компонентах.

Дочерний компонент использует данные следующим образом:

  const [data, setData] = React.useState<Array<any>>([]);

  React.useEffect(() => {
    const libraries = getLocalStorageItem('libraries');
    const softwareComponents = getLocalStorageItem('softwareComponents');
    const condition = libraries && softwareComponents;

    if (condition) {
      setData([...libraries, ...softwareComponents]);
    }
  }, []);

  const getDataLength = (category: string) => {
    return (data || []).filter((item: any) => item.category === category).length;
  };

  return (
    <React.Fragment>
      <OwcGrid item xs = {12} s = {4}>

        <LibrariesCard numberOfElements = {getDataLength('libraries')} /> // rendering here the length of the localStorage item.

      </OwcGrid>

Цель/вызов:

Я хочу использовать React.Context для удаления реализации локального хранилища, но я не уверен, как сделать это максимально простым.

Я видел только руководства, которые реализовывали действия отправки и т. д., но это кажется уже слишком сложным, потому что я только извлекаю данные и не изменяю их, поскольку я только визуализирую их.

Есть ли советы или руководства, как начать с этого?

Вы не должны использовать localStorage только для обмена состоянием. Вместо этого используйте Context с useState или useReducer. Вот статья о том, как это сделать, из документации по реакции: beta.reactjs.org/learn/scaling-up-with-reducer-and-context

Javokhir 10.10.2022 10:24
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
1
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Возможная реализация с контекстом:

//context.tsx
import {
  createContext,
  ReactNode,
  useContext,
  useEffect,
  useMemo,
  useState,
} from 'react';

export interface LibsAndComponentsInterface {
  data: unknown[];
}

const LibsAndComponentsContext = createContext<
  LibsAndComponentsInterface | undefined
>(undefined);

// Wrap your App component with this
export function LibsAndComponentsProvider({
  children,
}: {
  children: ReactNode;
}) {
  const [libs, setLibs] = useState<unknown[]>([]);
  const [components, setComponents] = useState<unknown[]>([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const libraries: unknown[] = await sendRequest('/libraries');
        const softwareComponents: unknown[] = await sendRequest(
          '/softwareComponents'
        );

        setLibs(libraries);
        setComponents(softwareComponents);
      } catch (err) {
        console.error(err);
      }
    };
    isAuthenticated() && fetchData();
  }, []);

  const ctxValue = useMemo(
    () => ({
      data: [...libs, ...components],
    }),
    [libs, components]
  );

  return (
    <LibsAndComponentsContext.Provider value = {ctxValue}>
      {children}
    </LibsAndComponentsContext.Provider>
  );
}

export function useLibsAndComponents() {
  const ctx = useContext(LibsAndComponentsContext);

  if (ctx == null) {
    throw new Error(
      'useLibsAndComponents must be inside LibsAndComponentsProvider'
    );
  }

  return ctx;
}
// later in your components

 const { data } = useLibsAndComponents()

Вот полная настройка React Context. Пожалуйста, используйте машинописный текст, если это необходимо.

MyContextProvider.js

const { createContext, useState } = require("react");

//Create a context
export const Mycontext = createContext();

//Created a component that helps to provide the context.
const MyContextProvider = ({ children }) => {

  //Declare all the states that you need
  const [libraries, setLibraries] = useState([]);
  const [softwareComponents, setSoftwareComponents] = useState([]);

  return (
    <Mycontext.Provider
      //provide all the state, function as value that you need in any child component 
      value = {{
        libraries,
        setLibraries,
        softwareComponents,
        setSoftwareComponents
      }}
    >
      {children}
    </Mycontext.Provider>
  );
};
export default MyContextProvider;

index.js

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import MyContextProvider from "./MyContextProvider";
import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
//Wrap App component By the MycontextProvider component
root.render(
  <StrictMode>
    <MyContextProvider>
      <App />
    </MyContextProvider>
  </StrictMode>
);

App.js

import { useContext } from "react";
import ChildComponent from "./Child";
import { Mycontext } from "./MyContextProvider";
import "./styles.css";


export default function App() {
  //This is the way of getting value from context here useContext is the builtin hook and Mycontext is the context name
  const { setLibraries, setSoftwareComponents } = useContext(Mycontext);
  //After getting data from API use setLibraries and setSoftwareComponents to store data in the state(context) instead of local storage.
  
  return (
    <div>
      <ChildComponent />
    </div>
    
  );
}

Ребенок.js

import { useContext } from "react";
import { Mycontext } from "./MyContextProvider";

const ChildComponent = () => {

  const { libraries, softwareComponents } = useContext(Mycontext);
  //Here is your state you can use it as your need.
  console.info(libraries, softwareComponents);
  
  return <h1>Child Component</h1>;
};
export default ChildComponent;

Другие вопросы по теме

Похожие вопросы