I'm getting the error "TypeError: properties.map is not a function", however when i console.log(properties) i can see the data. Can anyone explain me what i'm doing wrong? If i remove the map code obviously the error is not showing. Is it because "properties" is not defined yet during the render? I'm a bit confused of why it's not defined since as i said i can see the data on load with the console.
import React, { Component } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { AndroidOutlined, AppleOutlined } from '@ant-design/icons';
import Tabs, { TabPane } from '@iso/components/uielements/tabs';
import Select, { SelectOption } from '@iso/components/uielements/select';
import Button from '@iso/components/uielements/button';
import PageHeader from '@iso/components/utility/pageHeader';
import Box from '@iso/components/utility/box';
import { Form, Input, Checkbox, Col, Row } from 'antd'
import LayoutWrapper from '@iso/components/utility/layoutWrapper.js';
import ContentHolder from '@iso/components/utility/contentHolder';
import IntlMessages from '@iso/components/utility/intlMessages';
import FormGeneral from './FormGeneral';
import FormDetails from './FormDetails';
import propertiesActions from '@iso/redux/properties/actions';
const Option = SelectOption;
const {
loadFromApi,
} = propertiesActions;
export default function PropertiesPage() {
const dispatch = useDispatch();
React.useEffect(() => {
dispatch(loadFromApi());
}, [dispatch]);
const { properties, property, isLoading } = useSelector(
state => state.Properties
);
const rowStyle = {
width: '100%',
display: 'flex',
flexFlow: 'row wrap',
};
const colStyle = {
marginBottom: '16px',
};
const gutter = 16;
// Show data
console.log(properties);
console.log(isLoading);
return (
<LayoutWrapper>
<PageHeader>Properties</PageHeader>
<Box>
<Tabs defaultActiveKey="1">
<TabPane
tab={
<span>
<AppleOutlined />
General
</span>
}
key="1"
>
<div>
{console.log(properties)}
{properties.map(e =>
<div key={e.id}>
{e.id}
</div>
)}
</div>
<Row style={rowStyle} gutter={gutter} justify="start">
<Col md={12} sm={12} xs={24} style={colStyle}>
<Box>
<FormGeneral />
</Box>
</Col>
</Row>
</TabPane>
<TabPane
tab={
<span>
<AndroidOutlined />
Tab 2
</span>
}
key="2"
>
<FormDetails />
</TabPane>
</Tabs>
</Box>
</LayoutWrapper>
);
}
UPDATED:
properties is empty object at first
CodePudding user response:
What if you try properties?.map
, so it doesn't map if it is undefined, and wait until you really get the array. Because I don't have a big knowledge about redux, but from what I can read from your code, I understand that you are getting the properties asynchronously.
CodePudding user response:
By default properties
is undefined
. .map
cannot work with undefined
. Try to use:
const { properties = [], property, isLoading } = useSelector(
state => state.Properties
);
It is possible to extend the answer and change the initialState, but your reducer code is needed.
CodePudding user response:
before you map properties you should check if it is undefined because the initial value of state object in react is undefined and I think that if you will roll up in your console you should see an undefined print to the console
<div>
{console.log(properties)}
{properties !== undefined ? properties.map(e =>
<div key={e.id}>
{e.id}
</div>
): null}
</div>
CodePudding user response:
In fact the object was defined but empty, i had to check for the length
<div>
{console.log(properties)}
{properties.length > 1 ? properties.map(e =>
<div key={e.id}>
{e.id}
</div>
): null}
</div>
Doing this resolved the issue.