Redux State Management with a Input field

Viewed 83

Bit of a noob to redux but this appears to be quite a difficult question! I hope someone may be able to help me :)

I have build a page where you can input a search for different types of jobs. From this, it will make a get request to my DB and get all the info on this job. As this page is multi-levelled, I want to use redux to dispatch and pass the state throughout. This will help me pass my data on the job, e.g Data Analyst, through to each component so it can use the data and populate fields.

However, this was how my input field was originally setup:

export function SearchBarComp(props) {

    const [isExpanded, setExpanded] = useState(false);
    const [parentRef, isClickedOutside ] = useClickOutside();
    const inputRef = useRef();
    const [searchQuery, setSearchQuery] = useState("");
    const [isLoading, setLoading] = useState(false);
    const [jobPostings, setjobPostings] = useState([]);
    const [noRoles, setNoRoles] = useState(false)

    const isEmpty = !jobPostings || jobPostings.length === 0;

    const changeHandler = (e) => {
        //prevents defaulting, autocomplete
        e.preventDefault();
        if(e.target.value.trim() === '') setNoRoles(false);

        setSearchQuery(e.target.value);
    }

    const expandedContainer = () => {
        setExpanded(true);
    }


    //LINK THE BACKEND!
    const prepareSearchQuery = (query) => {
        //const url = `http://localhost:5000/api/role/title?title=${query}`;
        const url = `http://localhost:5000/api/role/titlerole?title=${query}`;


        //replaces bad query in the url
        return encodeURI(url);
    }

    const searchRolePosition = async () => {
        if(!searchQuery || searchQuery.trim() === "")
            return;

        setLoading(true);
        setNoRoles(false);

        const URL = prepareSearchQuery(searchQuery);

        const response = await axios.get(URL).catch((err) => {
            console.log(err);
        });


        if(response) {
            console.log("Response", response.data);

            if(response.data && response.data === 0)
                setNoRoles(true);

            setjobPostings(response.data);
        }

        setLoading(false);
    }

    useDebounce(searchQuery, 500, searchRolePosition)

    const collapseContainer = () => {
        setExpanded(false);
        setSearchQuery("");
         setLoading(false);
         setNoRoles(false);
        if (inputRef.current) inputRef.current.value = "";

      };

    // console.log("Value", searchQuery)

    useEffect(()=> {
        if(isClickedOutside)
            collapseContainer();
    }, [isClickedOutside])

    return (
    <SearchBarContainer animate = {isExpanded ? "expanded" : "collapsed"} 
                        variants={containerVariants} transition={containerTransition} ref={parentRef}>
        <SearchInputContainer>
            <SearchIconSpan>
                <SearchIcon/>
            </SearchIconSpan>
            <SearchInput placeholder = "Search for Roles" 
                                onFocus={expandedContainer} 
                                ref={inputRef}
                                value={searchQuery}
                                onChange={changeHandler}
                                />
            <AnimatePresence>
                {isExpanded && (<CloseIconSpan  key="close-icon" 
                                inital={{opacity:0, rotate: 0}} 
                                animate={{opacity:1, rotate: 180}} 
                                exit={{opacity:0, rotate: 0}} 
                                transition={{duration: 0.2}}
                                onClick={collapseContainer}>
                    <CloseIcon/>
                </CloseIconSpan>
                 )}
            </AnimatePresence>
        </SearchInputContainer>
        {isExpanded && <LineSeperator/>}
        {isExpanded && <SearchContent>

        {!isLoading && isEmpty && !noRoles && (
        <Typography color="gray" display="flex" flex="0.2" alignSelf="center" justifySelf="center">
                Start typing to search
        </Typography>
        )}
        
        {!isLoading && !isEmpty && <>
            {jobPostings.map((searchRolePosition) => (
                <JobSection
                    title={searchRolePosition.title}
                    //will need to do something like ----
                    //people = {searchRolePosition.title && searchRolePosition.title.average}
                    // future implementations
                />
            ))}    
        </>}
      
        </SearchContent>}
    </SearchBarContainer>
    )
}

As you can see, the main thing is the 'query' this creates a backend request to my titlerole, such as getting the data on Data Analyst. This all works in my frontend right now, but I can't pass that data down to the next component etc

So i'm looking to use redux.

I've created the following slice:

import { createSlice } from "@reduxjs/toolkit";

const jobSearchSlice = createSlice({
  name: "jobsearch",
  initialState: {
    currentRole: null,
    isFetching: false,
    error: false,
  },
  reducers: {
    jobsearchStart: (state) => {
      state.isFetching = true;
    },
    jobsearchSuccess: (state, action) => {
      state.isFetching = false;
      state.currentRole = action.payload;
    },
    jobsearchFailure: (state) => {
      state.isFetching = false;
      state.error = true;
    },
  },
});

export const { jobsearchStart, jobsearchSuccess, jobsearchFailure } = jobSearchSlice.actions;
export default jobSearchSlice.reducer;

With this, I'm also using the following apiCalls.js file:

import { jobsearchStart, jobsearchSuccess, jobsearchFailure } from "./jobsearchSlice";
import { publicRequest } from "../requestMethods";
export const roleSearchQuery = async (dispatch, jobsearch) => {
  dispatch(jobsearchStart());
  try{
    const res = await publicRequest.get("`http://localhost:5000/api/role/titlerole?title=${query}`", jobsearch);
    dispatch(jobsearchSuccess(res.data))
  }catch(err){
    dispatch(jobsearchFailure());
  }
};

My question is as a Redux noob, how do I implement this query functionality into a redux API request? What's the way to do this properly as I begin to tranisition this to an app which uses standard state management!

0 Answers
Related