I am trying to use MenuItem components with a React class component to display an array of strings as dropdown options in a Select component. In this snippet of code, I'm trying to retrieve these MenuItem components from the getGitRepoBranches(url) function call on line 11 and render them inside of my Select component:
1 {c.type === "git" ? <FormControl variant="outlined" size="small" style={{width: "20%", marginTop: "8px", marginRight: "0px"}}>
2 <InputLabel id="branch">Branch</InputLabel>
3 <Select
4 //error={!this.isGitRepoValid(c.url) && this.state.hasUserClickedSave}
5 //helperText={!this.isGitRepoValid(c.url) && this.state.hasUserClickedSave? INVALID_GIT_REPO_ERROR_MSG : ''}
6 labelId="branch-label"
7 id="demo-simple-select-helper"
8 label="Branch"
9 //onChange={(e) => this.editComponentHandler(e, i, "branch")}
10 >
11 {this.getGitRepoBranches(c.url)}
12 </Select>
13 {this.state.hasUserClickedSave ? (<FormHelperText style={{marginLeft: "0px"}} error>{INVALID_GIT_REPO_ERROR_MSG}</FormHelperText>) : null}
14 </FormControl> : null}
getGitRepoBranches() is retrieving data from an asynchronous API call fetchBranches, mapping the data to MenuItem components and returning them. It is defined like this:
getGitRepoBranches(url) {
fetchBranches(url)
.then((branches) => {
if (branches.length > 0) {
branches.map(branch => {
return (
<MenuItem value={branch}>
{branch}
</MenuItem>
)
})
}
else
return null
})
}
And fetchBranches is defined here:
1 export const fetchBranches = async (url: string): Promise<string[]> => {
2 let branches = <string[]>[];
3 ...
4 const URL: string = '/api/get_branches?'
5 new URLSearchParams(queryParams).toString();
6
7 try {
8 const response = await fetch(URL);
9 if (!response.ok) throw response.statusText;
10
11 const json = await response.json();
12 console.log("branches json:", json)
13 branches = createBranchesFromJSON(json);
14 ...
15 console.log("branches end of Api:", branches)
16 return Promise.resolve(branches);
17}
In fetchBranches, the console.log on line 15 shows that branches
is an array of strings. As per this post's suggestion: Why is then not working on this function, I tried returning a promise in the fetchBranches function to use in conjunction with .then in getGitRepoBranches(). After I fetch this promise's data (the array of strings) and map it to MenuItem components in getGitRepoBranches(), I want to render the components on line 11 in the first code snippet. Why am I incorrectly using Promise.then to use data and render it to my Select component?
CodePudding user response:
Move your asynchronous data fetching out of the render. Kick it off when your component (or a parent component) mounts, and then update state (or props) when you get the data.
function MySelect ({ dataUrl }) {
const [items, setItems] = useState([]);
useEffect(() => {
fetchData(dataUrl)
.then(data => setItems(data));
}, [dataUrl])
return (
<Select>
{ items.map(item => (
<MenuItem value={item} key={item}>{item}</MenuItem>
))}
</Select>
);
}
<MySelect dataUrl="/some/api/endpoint" />