Home > Mobile >  How to add an item to an array within context? (React typescript)
How to add an item to an array within context? (React typescript)

Time:01-07

I created a context search in my application, where I have an array called "searchPosts". My goal is to send an object from a component into this array in context and thus be able to use it in other components. I would like to create a global state where my object is stored

context

import { createContext } from "react";

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

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

provider

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>
    );
}

I created this search function because in theory it should be a function for me to add the item to the array, but I don't know how I could do that.

This is the state that I have in my component called "searchPosts" that I get the object that I would like to pass to my global array. I want to pass the information from this array in this component to my global array in context

  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);
  }
  

CodePudding user response:

In the component searchPosts, try to import SearchContext and import searchPost function from context component using useContext hook.

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

Now, inside your handleSearch function, pass the mapPosts array to searchPost function that you imported from useContext hook, like this:

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

Now, inside your searchPost function inside your provider component, add following code:

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

CodePudding user response:

Add the searchPost[] to SearchContextType

import { createContext } from "react";

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

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

Create a reducer to manage your dispatch

//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}`);
    }
  }
}

Create the provider

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 });

Now create a custom hook to access the context

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

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

  return context;
};

In your component, you can use the above to access the state.

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

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