yung peso
yung peso

Reputation: 1766

Why isn't useReducer state rendering new data successfully requested from API?

I have an input form that patches data. I would like the onSubmit function to send a render trigger to my useReducer that pulls data from my api get request and update my project with new data.

Right now the trigger is working but it's not causing a state re-render for the rest of the components. I know the trigger is working because of the successful api requests, but the new data is not showing up/

Here is the Parent component where the useReducer is. I then pass data from getFinData ran inside the useEffect to send data via state props to my Table component.

const initialState = {
    loading: true,
    error: '',
    data: []
}

const reducer = (state, action) =>
{
    switch (action.type)
    {
        case 'FETCH_SUCCESS':
            return {
                loading: false,
                data: action.payload,
                error: ''
            }
        case 'FETCH_ERROR':
            return {
                loading: false,
                data: {},
                error: "Something went wrong!"
            }
        default:
            return state
    }
}



export const Bucket = () => {
    const [state, dispatch] = useReducer(reducer, initialState)
    const { slug } = useParams();


    
    useEffect(() =>
    {
        getFinData(dispatch)(slug);
        console.log(state)
    }, [])

    return (
        <>
        <GetAboutBucketData /> //My input action lives deeply nested in GetAboutBucketData
        <GetBucketData  error={state.error} loading={state.loading} data={state.data}/>
        </>
    );

getFindData is it's own function in a different file.

export const getFinData = (dispatch) => (slug) => axiosInstance
        .get('bucket/fin-data/' + slug)
        .then(response => {
            dispatch({ type: 'FETCH_SUCCESS', payload: response.data })
            console.log('fired')
        })
        .catch(error => {
            dispatch({ type: 'FETCH_ERROR' })
        })

Here is GetBucketData:

function GetBucketData(props)
{
    const {data, loading, error} = props    
    return (
        <>
            <Tables error={error} loading={loading} data={data}/>
        </>
    );
};

export default GetBucketData;

my input onSubmit function where I want the request to cause a re-render for my useReducer.

  const onSubmit = (data, e) =>
  {  
    console.log(data);

    axiosInstance
      .patch(`bucket/add/symbols/` + slug + '/', {
        stock_list: data.stock_list.map(list=>list.symbol),
      })
      .then((res) =>
      {
        getFinData(dispatch)(slug);
      });
  };

How can I get my useReducers state to cause a re-render?

Upvotes: 0

Views: 248

Answers (1)

slaid3r
slaid3r

Reputation: 176

You could extract the logic of the useEffect to a function, call that function in the useEffect as well as pass it down to the form so it can be called inside the .then callback inside the onSubmit.

[UPDATE]

This is invalid as we have useReducer here from React not a Redux reducer.

You could extract the function to a separate file and provide dispatch with a higher order function. Keep in mind this is not the cleanest solution, lifting the state and fetch function up would be better.

//bucket-api.js

export const getFinData = (dispatch) => (slug) => axiosInstance
        .get('bucket/fin-data/' + slug)
        .then(response => {
            dispatch({ type: 'FETCH_SUCCESS', payload: response.data })
        })
        .catch(error => {
            dispatch({ type: 'FETCH_ERROR' })
        })

Then in both files you would simply call it like this:

const dispatch = useDispatch();
getFinData(dispatch)(slug);

Upvotes: 1

Related Questions