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)