Prop I can access in component can't be rendered - reactjs

My MERN app's purpose is to take a 3-digit input from a user and return the first prime number that contains those digits (ex: you enter 026, the app returns 10267). If my checker() function finds a match, I run updatePrimeNumber() to update that prime number's "match" variable to true. Database is updating properly.
I want to display all prime numbers that have "match" equal to true. I have a prop, primeNumbers, which contains all the primes I have entered into the database. I can access those numbers throughout my component, but I can not figure out how to render any of them, true or not. The error I receive is that primeNumbers is not defined.
import React, { Component } from 'react';
import gql from "graphql-tag";
import { graphql, compose } from 'react-apollo';
const PrimeNumbersQuery = gql`
{
primeNumbers {
id
text
match
}
}
`;
const UpdateMutuation = gql`
mutation($id: ID!, $match: Boolean!) {
updatePrimeNumber(id: $id, match: $match)
}
`;
class Prime extends Component {
checker = (primes) => {
let nums = this.props.checkedNumbersFromParent;
let recentChecked = (nums[nums.length - 1].text);
let recentCheckedRegExp = new RegExp(recentChecked);
for (var i in primes) {
let count = 0;
if (primes[i].text.search(recentCheckedRegExp) >= 0 && count < 1) {
this.updatePrimeNumber(primes[i]);
count = count + 1;
break;
}
}
return primes;
}
updatePrimeNumber = async (primeNumber) => {
await this.props.updatePrimeNumber({
variables: {
id: primeNumber.id,
match: primeNumber.match
},
update: store => {
const data = store.readQuery({ query: PrimeNumbersQuery });
data.primeNumbers = data.primeNumbers.map(
x =>
x.id === primeNumber.id
? {
...primeNumber, match: true
}
: x
);
store.writeQuery({ query: PrimeNumbersQuery, data });
}
});
};
render() {
const {data: {loading, primeNumbers}} = this.props;
this.checker(primeNumbers)
return (
<div>
***Need to render all primeNumbers with match === true***
</div>
);
}
}
export default compose(
graphql(UpdateMutuation, {name: 'updatePrimeNumber'}),
graphql(PrimeNumbersQuery)
)(Prime);
Thank you to anyone who looks at this. It is much appreciated.

About your problem:primeNumbers is not defined.UpdatePrimeNumber is async, you need to check it first and add constructor to initial this.props.
constructor(){
super(props)
}
renderprime(){
this.checker(this.props.data.primeNumbers)
if (this.props.data.primeNumbers){
return (
<div>
{this.props.data.primeNumbers.map((item) => {
if (item.match){
return (
<div>
<div>{item.id}</div>
<div>{item.text}</div>
</div>
)
}
})}
</div>
)
}
}
...
<div>
{this.renderprime()}
</div>

which line is the error being thrown from ?
You can try using the filter instead of updating the match in the primeNumber.
to render the prime numbers replace
Need to render all primeNumbers with match === true
loop through the primeNumbers

Related

react destructuring variable got undefined

I am new to react. My problem is that my variables keep saying that it is undefined. What I am trying to do is to display those variable but fail to destructure it. A filter function is executed and return a single tour. The data is successfully retrieved. By destructuring this, some variable contains an array can not be displayed. Does anyone know how to fix this?
TypeError: Cannot read property '0' of undefined
My data looks like this.
[
{
"_id": "12345",
"name": "I am first tour",
"startLocation": {
description: "USA",
type: "point"
},
"startDates": [
"2021-06-19T09:00:00.000Z",
"2021-07-20T09:00:00.000Z",
],
"imageUrl": [
"https://something1.jpg",
"https://something2.jpg",
"https://something3.jpg",
],
},
//.....rest data
]
import React, { Component } from 'react';
import './Tour.css';
import { connect } from 'react-redux';
class Tour extends Component {
constructor(props) {
super(props)
this.findSingletour = this.findSingletour.bind(this);
}
findSingletour = (tourId) => {
const notYetFilterTours = this.props.tours.tourState.data;
let filtered = [];
if (notYetFilterTours) {
filtered = notYetFilterTours.find((tour) => {
if (tour.id === tourId) {
return filtered;
}
return filtered;
});
}
return filtered;
};
render() {
const tourId = this.props.match.params._id;
let SingleTour = this.findSingletour(tourId);
const {
name,
startLocation,
startDates,
imageUrl
} = SingleTour;
return (
<div>
<span>{name}</span> // successfully rendered
<span>{startLocation[0]}</span> // undefined
<span>{startDates[0]}</span> // undefined
<span>{imageUrl[0]}</span> // undefined
</div>
)
}
}
const mapStateToProps = (state) => ({
tours: state.tourContainer,
});
export default connect(
mapStateToProps,
)(Tour);
Need to do validation just in case:
class Tour extends Component {
// some code
render() {
const {
name,
startLocation,
startDates,
imageUrl
} = SingleTour;
return (
<div>
<span>{name}</span> // successfully rendered
<span>{startLocation && startLocation.length > 0 ? startLocation[0] : ''}</span> // undefined
<span>{startDates && startDates.length > 0 ? startDates[0] : ''}</span> // undefined
<span>{imageUrl && imageUrl.length > 0 ? imageUrl[0] : ''}</span> // undefined
</div>
)
}
}
You can provide default values, and it is generally a good idea to have sensible defaults in case data is not loaded and UI is rendered.
So something like this would prevent such errors:
const {
name = '',
startLocation = [],
startDates = [],
imageUrl = ''
} = SingleTour;
Now if your UI renders and tries to get 0 of startLocation, it won't fail. It will of course find nothing, and display nothing except the UI skeleton, but the app will not error out.

React: An component attribute is not properly storing the data (from a query) that I want

I recently started learning react and I have encountered something that I do not understand. So when I declare a component I also declare an attribute in the constructor. Then, after executing the first query (I am using Apollo client - GraphQL ) I want to store the result (which I know that will be always an email) in the attribute declared so I can use it as a parameter in the second query.
The app logic is that I want to show all the orders of a given email, but first I get the email with a query.
Here is the code:
export default class Orders extends Component {
constructor(){
super();
this.email = '';
}
render() {
return (
<div>
<Query query = { GET_MAIL_QUERY }>
{({data, loading}) => {
if (loading) return "Loading...";
this.email = data.me.email;
return <h1>{this.email}</h1>
}}
At this point a header containing the email is returned, so all good. But when I execute the second query (or try to display the email in the second header for that matter) it seems that the value is not properly stored.
</Query>
<h1>{this.email}</h1>
<Query query = { GET_ORDERS_QUERY }
variables = {{
email: this.email
}}>
{({data, loading}) => {
if (loading) return "Loading...";
console.log(data);
let orders = data.ordersByEmail.data;
console.log(orders);
return orders.map(order =>
<div>
<h1>{order.date}</h1>
<h1>{order.price}</h1>
<h1>{order.conference.conferenceName}</h1>
<h1>{order.user.email}</h1>
<br></br>
</div>)
}}
</Query>
</div>
)
}
}
const GET_MAIL_QUERY = gql`
query getMyMail{
me{
email
}
}
`;
const GET_ORDERS_QUERY = gql`
query getOrdersByEmail($email: String!) {
ordersByEmail(email: $email) {
data {
gid
date
price
user {
email
}
conference{
conferenceName
}
}
}
}
`;
I would love an explanation for this and maybe a solution (to store a value returned from a query to use it in another)
Thanks in anticipation :)
In my experience, you should use useQuery imported from #apollo/react-hooks with functional component because it's easy to use, it makes your code more cleaner
If your want to use <Query/> component with class component, it's ok. But, if you want to store data received from server, you should create a variable in state of constructor and when you want to update to state, you should use this.setState({email: data.me.email}). Don't use this.state.email = data.me.email, it's anti-pattern, React will not trigger re-render when you use it to update your state.
This is the code:
import React, { useState } from 'react'
import gql from 'graphql-tag'
import { useQuery, useMutation } from '#apollo/react-hooks'
const GET_MAIL_QUERY = gql`
query getMyMail {
me {
email
}
}
`
const GET_ORDERS_QUERY = gql`
query getOrdersByEmail($email: String!) {
ordersByEmail(email: $email) {
data {
gid
date
price
user {
email
}
conference {
conferenceName
}
}
}
}
`
const Orders = () => {
const [email, setEmail] = useState('')
const { data: getMailQueryData, loading, error } = useQuery(GET_MAIL_QUERY, {
onCompleted: data => {
setEmail(data.me.email)
},
onError: err => alert(err),
})
const { data: getOrdersQueryData } = useQuery(GET_ORDERS_QUERY, {
variables: { email: email },
})
if (loading) return <div>Loading...</div>
if (error) return <div>Error...</div>
return ...
}

Why PropTypes failed with Value is undefined

I cannot figure out why prototypes in my function component in React fails with this:
`index.js:1 Warning: Failed prop type: The prop `profiles` is marked as required in `Home`, but its value is `undefined`.`
The app is working fine and Profiles is defined and I'm using React-redux with hooks and maybe that causing the issue becasue I don't know actually what to do to make the PropTypes to work
My home where this come ups:
import React, { useEffect, useState } from "react";
import { Row, Col, Jumbotron, Container, Image } from "react-bootstrap";
import { ProfileMiddleware } from "../Store/Middleware";
import { PropTypes } from "prop-types";
import { useDispatch, useSelector } from "react-redux";
import { USERNAME } from "../Services/constAPI";
import Experiences from "../Components/Experiences/Experiences";
import { Spinner } from "../Components/Spinner/Spinner.js";
const Home = () => {
const dispatch = useDispatch();
const { profiles, displaySpinner } = useSelector(state => ({
profiles: state.ProfileReducer.profiles,
displaySpinner: state.ProfileReducer.displaySpinner
}));
useEffect(() => {
dispatch(ProfileMiddleware.getOneProfile(USERNAME));
}, [dispatch]);
return !profiles.object ? (
<>
<Jumbotron>
<Container>
<Row>
<Col md={6}>
<Image src={profiles.imageUrl} alt="profile" roundedCircle />
</Col>
<Col md={6}>
<h1>{profiles.firstname + " " + profiles.surname}</h1>
<h4>{profiles.title}</h4>
<h5>{profiles.area}</h5>
<p>{profiles.email}</p>
<p>{profiles.bio}</p>
</Col>
</Row>
<Spinner displaySpinner={displaySpinner} />
</Container>
</Jumbotron>
<Experiences />
</>
) : (
<h3 className="red-text mt-5">The profile is not available</h3>
);
};
Home.propTypes = {
profiles: PropTypes.object.isRequired
};
export default Home;
The reducer as I'm using Redux
import { ProfileActions } from "../Actions";
function ProfileReducer(
state = {
profiles: {},
displaySpinner: false
},
action
) {
console.log("data in action", action.data);
console.log("Action type", action.type);
switch (action.type) {
case ProfileActions.GET_ONE_PROFILE:
return {
...state,
displaySpinner: true
};
case ProfileActions.GET_ONE_PROFILE_SUCCESS:
return {
...state,
profiles: action.data,
displaySpinner: false
};
default:
return state;
}
}
export default ProfileReducer;
I can show else if necessary but the APP works but PropTypes saying profiles are undefined that I cannot understand.
You're not passing in any props to Home. If you were, it would look something like
const Home = (props) => {
Instead, you are getting profiles from your redux store. So simply change
Home.propTypes = {
profiles: PropTypes.object.isRequired
};
to
Home.propTypes = {};
profiles is not a prop being passed to Home. The proptypes for the Home component should be deleted.
You say in the comments:
I have to check the profiles to be an obj with PropTypes I'm trying to find a solution to make it works. If you know a solution please share an answer
If you can guarantee that in your selector that's even better, but there're ways to do so in the component.
So let's take a snippet of your code and do that:
const Home = () => {
const dispatch = useDispatch();
const { profiles, displaySpinner } = useSelector(state => ({
profiles: state.ProfileReducer.profiles,
displaySpinner: state.ProfileReducer.displaySpinner
}));
// note Array's and other variable are also objects
// so we need to do a special check
const isProfilesAnObject = profiles && profiles.constructor.name === 'Object';
// created outside of `every` loop, and ternary shortcut to empty array
const profilesKeys = isProfilesAnObject ? Object.keys(profiles) : [];
// check that profileKeys is a subset of REQUIRED_KEYS
// n.b. you need to define this somewhere
const isProfilesCorrect = REQUIRED_KEYS.every(requiredKey => profileKeys.includes(requiredKey))
useEffect(() => {
dispatch(ProfileMiddleware.getOneProfile(USERNAME));
}, [dispatch]);
return isProfilesCorrect ?
This should work like below:
const checkProfiles = profiles => {
const REQUIRED_KEYS = ['a', 'b', 'z', 'y']
const isProfilesAnObject = profiles && profiles.constructor.name === 'Object';
// created outside of `every` loop, and ternary shortcut to empty array
const profilesKeys = isProfilesAnObject ? Object.keys(profiles) : [];
// check that profileKeys is a subset of REQUIRED_KEYS
// n.b. you need to define this somewhere
const isProfilesCorrect = REQUIRED_KEYS.every(requiredKey => profilesKeys.includes(requiredKey))
return isProfilesCorrect;
}
const [profile1, profile2, profile3] = [{
'a': '10'
}, {
a: '10', b: '20', z: '260', y: '250'
},{
a: '10', b: '20', extra_key: 'I\'m being a little bit extra', z: '260', y: '250'
}]
// missing keys
console.log(`profile1 (with keys ${Object.keys(profile1)}) is: ${checkProfiles(profile1) ?'correct': 'incorrect'}`);
// just the right number of keys
console.log(`profile2 (with keys ${Object.keys(profile2)}) is: ${checkProfiles(profile2) ?'correct': 'incorrect'}`);
// doesn't check if there aren't extra keys
console.log(`profile3 (with keys ${Object.keys(profile3)}) is: ${checkProfiles(profile3) ?'correct': 'incorrect'}`);
There is also invariant which you can use for stricter checking. It throws an error if something is false, so you can put exact checking in there, as seen below.
(n.b. ignore the process and module objects I had to define, and note I'm using tiny-invariant for convenience )
const checkProfiles = profiles => {
const REQUIRED_KEYS = ['a', 'b', 'z', 'y']
const isProfilesAnObject = profiles && profiles.constructor.name === 'Object';
// created outside of `every` loop, and ternary shortcut to empty array
const profilesKeys = isProfilesAnObject ? Object.keys(profiles) : [];
// check that profileKeys is a subset of REQUIRED_KEYS
// n.b. you need to define this somewhere
const isProfilesCorrect = REQUIRED_KEYS.every(requiredKey => profilesKeys.includes(requiredKey))
// really need to make sure 'z' exists and is a string
invariant(typeof profiles.z === 'string', `Profiles is expected to have a key 'z' that is a string, but found ${JSON.stringify(profiles.z)}`)
return isProfilesCorrect;
}
console.log(checkProfiles({
a: 10,
z: 'valid'
}))
try {
checkProfiles({
a: 10,
z: 20
});
} catch (e) {
console.error(e);
}
<script>
var process = {
env: 'production'
}
var module = {
exports: {}
}
</script>
<script src="https://cdn.jsdelivr.net/npm/tiny-invariant#1.2.0/dist/tiny-invariant.cjs.min.js">
</script>
Either of those should work depending on how seriously you need to make sure your variables exist and are correct
Actually, you didn't pass props, pay attention to:
const Home = () => {
You should write const Home = props => { or destruct the props in the beginning of your function component, like below:
const Home = ({ profiles }) => {
And then use it inside your execution context of the function component. Also, you can put the default value for your props like below:
const Home = ({ profiles = 'something' }) => {
The 'something' is a sample, it can be everything, or write like below at the end of your function component declaration:
Home.defaultProps = {
profiles: 'something'
};
I hope it helps you, but surely you should read the ReactJS docs a little bit more.

Dealing with ag grid react and rendering a grid of checkboxes

I'm messing with ag-grid, react-apollo, and everything seems to be working fine. The goal here is to click a check box and have a mutation / network request occur modifying some data. The issue i'm having is that it redraws the entire row which can be really slow but im really just trying to update the cell itself so its quick and the user experience is better. One thought i had was to do a optimistic update and just update my cache / utilize my cache. What are some approach you guys have taken.
Both the columns and row data are grabbed via a apollo query.
Heres some code:
CheckboxRenderer
import React, { Component } from "react";
import Checkbox from "#material-ui/core/Checkbox";
import _ from "lodash";
class CheckboxItem extends Component {
constructor(props) {
super(props);
this.state = {
value: false
};
this.handleCheckboxChange = this.handleCheckboxChange.bind(this);
}
componentDidMount() {
this.setDefaultState();
}
setDefaultState() {
const { data, colDef, api } = this.props;
const { externalData } = api;
if (externalData && externalData.length > 0) {
if (_.find(data.roles, _.matchesProperty("name", colDef.headerName))) {
this.setState({
value: true
});
}
}
}
updateGridAssociation(checked) {
const { data, colDef } = this.props;
// const { externalData, entitySpec, fieldSpec } = this.props.api;
// console.log(data);
// console.log(colDef);
if (checked) {
this.props.api.assign(data.id, colDef.id);
return;
}
this.props.api.unassign(data.id, colDef.id);
return;
}
handleCheckboxChange(event) {
const checked = !this.state.value;
this.updateGridAssociation(checked);
this.setState({ value: checked });
}
render() {
return (
<Checkbox
checked={this.state.value}
onChange={this.handleCheckboxChange}
/>
);
}
}
export default CheckboxItem;
Grid itself:
import React, { Component } from "react";
import { graphql, compose } from "react-apollo";
import gql from "graphql-tag";
import Grid from "#material-ui/core/Grid";
import _ from "lodash";
import { AgGridReact } from "ag-grid-react";
import { CheckboxItem } from "../Grid";
import "ag-grid/dist/styles/ag-grid.css";
import "ag-grid/dist/styles/ag-theme-material.css";
class UserRole extends Component {
constructor(props) {
super(props);
this.api = null;
}
generateColumns = roles => {
const columns = [];
const initialColumn = {
headerName: "User Email",
editable: false,
field: "email"
};
columns.push(initialColumn);
_.forEach(roles, role => {
const roleColumn = {
headerName: role.name,
editable: false,
cellRendererFramework: CheckboxItem,
id: role.id,
suppressMenu: true,
suppressSorting: true
};
columns.push(roleColumn);
});
if (this.api.setColumnDefs && roles) {
this.api.setColumnDefs(columns);
}
return columns;
};
onGridReady = params => {
this.api = params.api;
this.columnApi = params.columnApi;
this.api.assign = (userId, roleId) => {
this.props.assignRole({
variables: { userId, roleId },
refetchQueries: () => ["allUserRoles", "isAuthenticated"]
});
};
this.api.unassign = (userId, roleId) => {
this.props.unassignRole({
variables: { userId, roleId },
refetchQueries: () => ["allUserRoles", "isAuthenticated"]
});
};
params.api.sizeColumnsToFit();
};
onGridSizeChanged = params => {
const gridWidth = document.getElementById("grid-wrapper").offsetWidth;
const columnsToShow = [];
const columnsToHide = [];
let totalColsWidth = 0;
const allColumns = params.columnApi.getAllColumns();
for (let i = 0; i < allColumns.length; i++) {
const column = allColumns[i];
totalColsWidth += column.getMinWidth();
if (totalColsWidth > gridWidth) {
columnsToHide.push(column.colId);
} else {
columnsToShow.push(column.colId);
}
}
params.columnApi.setColumnsVisible(columnsToShow, true);
params.columnApi.setColumnsVisible(columnsToHide, false);
params.api.sizeColumnsToFit();
};
onCellValueChanged = params => {};
render() {
console.log(this.props);
const { users, roles } = this.props.userRoles;
if (this.api) {
this.api.setColumnDefs(this.generateColumns(roles));
this.api.sizeColumnsToFit();
this.api.externalData = roles;
this.api.setRowData(_.cloneDeep(users));
}
return (
<Grid
item
xs={12}
sm={12}
className="ag-theme-material"
style={{
height: "80vh",
width: "100vh"
}}
>
<AgGridReact
onGridReady={this.onGridReady}
onGridSizeChanged={this.onGridSizeChanged}
columnDefs={[]}
enableSorting
pagination
paginationAutoPageSize
enableFilter
enableCellChangeFlash
rowData={_.cloneDeep(users)}
deltaRowDataMode={true}
getRowNodeId={data => data.id}
onCellValueChanged={this.onCellValueChanged}
/>
</Grid>
);
}
}
const userRolesQuery = gql`
query allUserRoles {
users {
id
email
roles {
id
name
}
}
roles {
id
name
}
}
`;
const unassignRole = gql`
mutation($userId: String!, $roleId: String!) {
unassignUserRole(userId: $userId, roleId: $roleId) {
id
email
roles {
id
name
}
}
}
`;
const assignRole = gql`
mutation($userId: String!, $roleId: String!) {
assignUserRole(userId: $userId, roleId: $roleId) {
id
email
roles {
id
name
}
}
}
`;
export default compose(
graphql(userRolesQuery, {
name: "userRoles",
options: { fetchPolicy: "cache-and-network" }
}),
graphql(unassignRole, {
name: "unassignRole"
}),
graphql(assignRole, {
name: "assignRole"
})
)(UserRole);
I don't know ag-grid but ... in this case making requests results in entire grid (UserRole component) redraw.
This is normal when you pass actions (to childs) affecting entire parent state (new data arrived in props => redraw).
You can avoid this by shouldComponentUpdate() - f.e. redraw only if rows amount changes.
But there is another problem - you're making optimistic changes (change checkbox state) - what if mutation fails? You have to handle apollo error and force redraw of entire grid - change was local (cell). This can be done f.e. by setting flag (using setState) and additional condition in shouldComponentUpdate.
The best way for me to deal with this was to do a shouldComponentUpdate with network statuses in apollo, which took some digging around to see what was happening:
/**
* Important to understand that we use network statuses given to us by apollo to take over, if either are 4 (refetch) we hack around it by not updating
* IF the statuses are also equal it indicates some sort of refetching is trying to take place
* #param {obj} nextProps [Next props passed into react lifecycle]
* #return {[boolean]} [true if should update, else its false to not]
*/
shouldComponentUpdate = nextProps => {
const prevNetStatus = this.props.userRoles.networkStatus;
const netStatus = nextProps.userRoles.networkStatus;
const error = nextProps.userRoles.networkStatus === 8;
if (error) {
return true;
}
return (
prevNetStatus !== netStatus && prevNetStatus !== 4 && netStatus !== 4
);
};
It basically says if there is a error, just rerender to be accurate (and i think this ok assuming that errors wont happen much but you never know) then I check to see if any of the network statuses are not 4 (refetch) if they are I dont want a rerender, let me do what I want without react interfering at that level. (Like updating a child component).
prevNetStatus !== netStatus
This part of the code is just saying I want the initial load only to cause a UI update. I believe it works from loading -> success as a network status and then if you refetch from success -> refetch -> success or something of that nature.
Essentially I just looked in my props for the query and saw what I could work with.

Graphql query result comes back undefined

I am getting the error Uncaught (in promise) TypeError: Cannot read property 'privateKey' of undefined
Employee query result comes back undefined when trying to console.log this.props.employee
I am using Graphql and Next.js. Am unsure whether or not componentWillMount is the correct lifecyle method to use as this.props.data.employee is undefined.
class EmployeeTable extends Component {
state = {
employeesList: [],
privateKey: ""
}
fetchEmployees = async () => {
console.log(this.props.data.employee);
console.log(this.props.data.employee.privateKey);
const adminWallet = new ethers.Wallet(this.state.privateKey, provider);
const EmployeeStore = new ethers.Contract(address, abi, adminWallet);
let count;
await EmployeeStore.functions.employeesCount().then(function(value) {
count = value;
});
let employeesList = [];
for(let i = 1; i<=count; i++) {
await EmployeeStore.getEmployeeByIndex(i).then(function(result) {
employeesList.push(result);
});
};
console.log(employeesList);
return {employeesList};
};
componentWillMount = async () => {
var employees = await this.fetchEmployees();
this.setState({employeesList: employees});
};
renderRows() {
return this.state.employeesList.map((employee, index) => {
return (<EmployeeRow
key={index}
employee={employee}
/>
);
});
};
render() {
const { Header, Row, HeaderCell, Body } = Table;
return(
<div>
<h3>Employees</h3>
<Table>
<Header>
<Row>
<HeaderCell>Name</HeaderCell>
<HeaderCell>Employee ID</HeaderCell>
<HeaderCell>Address</HeaderCell>
<HeaderCell>Authenticated</HeaderCell>
</Row>
</Header>
<Body>{this.renderRows()}</Body>
</Table>
</div>
)
}
}
const employee = gql`
query employee($employeeID: String){
employee(employeeID: $employeeID) {
privateKey
}
}
`;
export default graphql(employee, {
options: {
variables: {employeeID: "1234"}
},
})
(EmployeeTable);
The first time a component wrapped with a Query operation, like in your code, is rendered it receives the data prop but without the results yet.
data contains a field called loading. If it is set to true, it means the query didn't receive all the results from the server yet. If the operation is successful, next time your component is rendered this.props.data will have loading === false and this.props.data.employee should be have a value as you expect.
Basically, you should check if this.props.data.loading is true or false before calling fetchEmployees() and before rendering child components that rely on the results.

Resources