Reputation: 87
I am trying to get a child component to render only when the Context API state that I set up is fully mounted. The Parent component is grabbing from the server and setting the state based on the information received. I keep getting Undefined in the first render, then it re-renders and it comes out as an Array. I want only to render this component so the Child may render it's component without any errors. I've attempted to use the UseEffect but I don't understand it that well..
Here is the Child Component...
import React, { useState, useContext, useEffect } from "react";
import styles from "./bathoneform.module.css";
import Ratings from "../Ratings";
import {
BathOneFormContext,
FormQuestionsContext,
} from "../../Store";
function BathOneForm() {
const [formQuestions, setFormQuestions] = useContext(FormQuestionsContext);
const [bathOneFormAnswers, setBathOneFormAnswers] = useContext(
BathOneFormContext
);
//setting the array
const array = formQuestions.bathone;
const handleChange = (e) => {
const { name, value } = e.target;
setBathOneFormAnswers((state) => ({ ...state, [name]: value }));
};
console.log(formQuestions);
return (
<div>
<form
className={styles["BathroomOneFormWrapper"]}
id="bathroom-one-form"
onChange={handleChange}
>
{array.map((object, index) => {
return (
<div className={styles["CheckboxWrapper"]} key={index}>
<h5>{object}</h5>
<Ratings
Question={object}
/>
</div>
);
})}
</form>
</div>
);
}
export default BathOneForm;
Here is the code from Parent Component where I grab from the server...
export default function MoveInForm({ Apartment }) {
const [formQuestions, setFormQuestions] = useContext(FormQuestionsContext);
const [state, setState] = useContext(FormSectionsContext);
const getData = async () => {
const apartmentName = Apartment.toLowerCase();
let headers = new Headers();
headers.append("Content-Type", "application/json");
headers.append("Accept", "application/json");
headers.append("Origin", "http://localhost:3000");
const response = await axios.get(
`http://localhost:5000/api/${apartmentName}`,
headers
);
await setFormQuestions(response.data[0].bathone);
};
useEffect(() => {
getData();
}, []);
App.js....
import React, { useState } from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-
dom";
import styles from "./App.module.css";
import DocumentTitle from "react-document-title";
import MoveInForm from "./pages/MoveInForm";
import NoMatch from "./components/NoMatch";
import Store from "./Store";
import axios from "axios";
function App() {
const [state, setState] = useState(false);
//Title Case
String.prototype.toProperCase = function () {
return this.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
};
const renderMoveIn = (routerProps) => {
const Name = routerProps.match.params.apartment.toLowerCase();
let headers = new Headers();
headers.append("Content-Type", "application/json");
headers.append("Accept", "application/json");
headers.append("Origin", "http://localhost:3000");
axios
.get(`http://localhost:5000/api/${Name}`, headers)
.then((res) => {
setState(true);
})
.catch((error) => {
console.log(error);
});
const Apartment = apartmentName.toProperCase();
return state ? <MoveInForm Apartment={Apartment} /> : <NoMatch />;
};
return (
<DocumentTitle title="Move-In Inspection">
<Store>
<Router>
<div className={styles["App"]}>
<Switch>
<Route
path="/:apartment"
render={(routerProps) => renderMoveIn(routerProps)}
/>
<Route component={NoMatch} />
</Switch>
</div>
</Router>
</Store>
</DocumentTitle>
);
}
export default App;
Upvotes: 0
Views: 262
Reputation: 1352
It would appear that the DOM will render first, before the promise
is resolved
or fulfilled
. As the promise
runs on the network thread, it will queue the result callback in the micro task
thread, which will run after the DOM has completed its first render.
What you can do is
isLoading
state in the component, and set it to true
for the initial value. And set it to false
after the promise
resolves.if
condition in the component to load an empty div
if the array is empty.Upvotes: 1