reactjs - Bir öğeyi bağlam içindeki bir diziye nasıl eklerim? (React typescript)


Uygulamamda bir bağlam araması oluşturdum, burada "searchPosts" adında bir dizim var. Amacım, bir bileşenden bu dizideki bağlama bir nesne göndermek ve böylece diğer bileşenlerde kullanabilmek. Nesnemin saklandığı küresel bir durum oluşturmak istiyorum.

bağlam

import { createContext } from "react";

export type SearchContextType = {
    searchPost: (text: string) => void;
};

export const SearchContext = createContext<SearchContextType>(null!);

sağlayıcı

import React, { useState } from "react";
import { SearchContext } from "./SearchContext"

export const SearchProvider = ({ children }: { children: JSX.Element }) => {
    const [searchPosts, setSearchPosts] = useState([]);

    const searchPost = (text: string) => {

    }

    return (
        <SearchContext.Provider value={{searchPost}}>
            { children }
        </SearchContext.Provider>
    );
}

Bu arama işlevini oluşturdum çünkü teoride benim için öğeyi diziye eklemek için bir işlev olmalı, ama bunu nasıl yapabileceğimi bilmiyorum.

Bu, benim "searchPosts" adlı bileşenimde sahip olduğum durumdur; bu durum, global dizime aktarmak istediğim nesneyi aldığım yerdir. Bu bileşendeki bu diziden gelen bilgileri, bağlamdaki global dizime aktarmak istiyorum.

  const navigate = useNavigate();
  const api = useApi();

  const [searchText, setSearchText] = useState('');
  const [searchPost, setSearchPost] = useState([]);

  const handleSearch = async () => {
    const posts = await api.getAllPosts();
    const mapPosts = posts.filter(post => post.title.toLowerCase().includes(searchText));
    setSearchPost(mapPosts);
  }
  

Cevap #1

searchPosts bileşeninde, SearchContext'i içe aktarmayı ve context bileşeninden searchPost fonksiyonunu useContext kancası kullanarak içe aktarmayı deneyin.

import {SearchContext} from './SearchContext'
const {searchPost} = useContext(SearchContext);;

Şimdi, handleSearch fonksiyonunuzun içinde, mapPosts dizisini, useContext kancasından içe aktardığınız searchPost fonksiyonuna şu şekilde geçirin:

const handleSearch = async () => {
    const posts = await api.getAllPosts();
    const mapPosts = posts.filter(post => post.title.toLowerCase().includes(searchText));
    setSearchPost(mapPosts);
    searchPost(mapPosts);
  }

Şimdi, provider bileşeninizin içindeki searchPost fonksiyonunun içine aşağıdaki kodu ekleyin:

const searchPost = (posts: any[]) => {
  setSearchPosts(prev => {
     return [...prev, ...posts];
  })
}

Cevap #2

searchPost[] öğesini SearchContextType'a ekleyin

import { createContext } from "react";

export type SearchContextType = {
  searchPost: (text: string) => void;
  searchResult: string[];
};

export const SearchContext = createContext<SearchContextType>(null!);

Gönderiminizi yönetmek için bir azaltıcı oluşturun

//const SEARCH_POST = "SEARCH_POST"; in constants.ts
import { SEARCH_POST } from 'constants';
// reducer
export const reducer = (state, action) => {
  switch (action.type) {
    case SEARCH_POST: {
      return { ...state, searchResult: action.value };
    }
    default: {
      throw new Error(`Unhandled action type: ${action.type}`);
    }
  }
}

Sağlayıcıyı oluştur

interface InitState {
  searchResult: string[];
}

export const SearchProvider = ({ children }: { children: JSX.Element }) => {
  const initialState: InitState = {
    searchResult: [],
  };

  const [controller, dispatch] = useReducer(reducer, initialState);

  const value = useMemo(() => [controller, dispatch], [controller, dispatch]);

  return <SearchContext.Provider value={value}>{children}</SearchContext.Provider>;
};


export const searchPost = (dispatch, value) => dispatch({ type: SEARCH_POST, value });

Şimdi konteks'e erişmek için özel bir hook oluşturun

export const useSearchState = () => {
  const context = useContext(SearchContext);

  if (!context) {
    throw new Error(
      "useSearchState should be used inside the SearchProvider."
    );
  }

  return context;
};

Bileşeninizde duruma erişmek için yukarıdakini kullanabilirsiniz.

const [controller, dispatch] = useSearchState();
const {searchResult} = controller;

// to update the post you can call searchPost
// import it from search provider
searchPost(dispatch, posts)