Reputation: 119
react component with hooks:
Requirement: when page load, data populates, from backend, into dropdowns and multi-select tables(tables with checkboxes). On the Submit button click, I need to use this consolidates object (for the default values selected) to make another REST call.
NOTE: No change handler called for any of these ui components.
Issue:
Suggestion needed: is there a way to setState of the default selected values on form load event.
const [data, setData] = useState(undefined);
const changeRequests = useSelector(state =>
state.oncallRequest.changeRequests
);
useEffect(() => {
if (!changeRequests.fulfilled) {
dispatch(fetchRequests(), [dispatch])
.then(response => setData(setDefaultState(response.data)));
}
}, [changeRequests.fulfilled, dispatch]);
And I got the below error:
ERROR: TypeError: Cannot read property 'then' of undefined.async call.
Action Class:
export const fetchRequests = () => dispatch => {
dispatch({type: LIST_PENDING});
listChangeRequests().then(data => {
dispatch({type: LIST_FULFILLED, changeRequests: data})
}).catch(err => {
dispatch({type: LIST_FAILED, changeRequests: {error: err.message}})
});
};
**Service Class**
export const listChangeRequests = () => axiosInstance.get(`/getData`).then(res => {
return res.data;
});
SOLUTION:
I used 2 use Effect: one for fetching data from backend and another for setting state.
**but getting the following exception**
1) **React Hook useEffect has a missing dependency: 'setDefaultState'. Either include it or remove the dependency array**
2) 'data' is assigned a value but never used
Please advise on the warnings...
useEffect(() => {
if (!changeRequests.fulfilled) {
dispatch(fetchRequests(), [dispatch])
}
}, [changeRequests.fulfilled, dispatch]);
-------------
useEffect(() => {
if (changeRequests.data) {
setData(setDefaultState(changeRequests.data));
}
}, [changeRequests.data]);
Upvotes: 0
Views: 9314
Reputation: 32522
Likely, you don't know useEffect
, at the initial mounting of your component the useEffect
can call an API and then change the state by using useState
. like below:
import React, { useState, useEffect } from 'react';
const FormComponent = () => {
const [data, setData] = useState(undefined);
const [error, setError] = useState(undefined);
useEffect(() => {
// call an API and in the success or failure fill the data by using setData function
// It could be like below
ApiCall()
.then(response => setData(response))
.catch(err => setError(err))
}, []);
~~~
};
UPDATE
This part is added after your code adding. actually your dispatch
function doesn't return Promise
event doesn't return anything. so the usage of then
in your code is not acceptable and the JavaScript interpreter should return an Error. I guess you should focus on your dispatch
function.
Upvotes: 3
Reputation: 5854
You need to use useEffect and useState Hooks for this.
useEffect(() => {
// write any code that will execute at first time
}, []); <-- [] is the empty dependency.
In the below example, LoadUser() function is called in useEffect that will be getting data from api. After successful call, response data is set into the state using setPosts (useState Hook)
import React, { useEffect, useState } from "react";
import axios from "axios";
function ExamplePost() {
const [isLoading, setIsLoading] = useState(false);
const [posts, setPosts] = useState([]);
const [error, setError] = useState("");
useEffect(() => {
LoadUser();
}, []);
function LoadUser() {
try {
setIsLoading(true);
const response = axios.get(`https://jsonplaceholder.typicode.com/posts`, {
cancelToken: this.signal.token
});
response
.then((response) => {
setPosts(response);
setIsLoading(false);
})
.catch((error) => {
setError(error);
setIsLoading(false);
});
} catch (error) {
setIsLoading(false);
}
}
return (
<div>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
export default ExamplePost;
Upvotes: -1