I am trying to pass an array of objects to mock component data for testing like so:
const mockPackage = {
id: '1232-1234-12321-12321',
name: 'Mock Package',
price: 8.32,
description: 'Mock description',
globalProduct: {
imageUrl: 'http://imageurl.com',
},
};
const mockPackageData = {
name: 'Package',
packages: [mockPackage],
};
beforeEach(() => {
component = render(
<SuiteContextProvider>
<PackageCard
showDetail={{ display: true, selectedIndex: 1, hideOthers: false }}
handleShowDetail={handleShowDetail}
packageData={mockPackageData}
/>
</SuiteContextProvider>,
);
});
However, I receive the following error:
The component that receives the data destructures the packageData like so:
export interface Package {
id: string;
name: string;
price: number;
description: string;
globalProduct: {
imageUrl: string;
};
}
export interface PackageData {
name: string;
packages: [];
}
type Props = {
packageData: PackageData;
handleShowDetail: (data: DefaultPackageProps) => void;
showDetail: {
display: boolean;
selectedIndex: number | null;
hideOthers: boolean;
};
};
const PackageCard: React.FC<Props> = ({ packageData, handleShowDetail, showDetail }: Props) => {
return (
<>
{packageData.packages.map((packageInfo: Package, index: number) => {
const {
id,
name,
price,
description,
globalProduct: { imageUrl },
} = packageInfo;
Your PackageData defintion should be
export interface PackageData {
name: string;
packages: Package[];
}
You current code packages: []; declares packages to must be an empty array that is why you get the type '0' error.
Related
Here is the data from the server.
I want to display it with map on UI.
Here is the interface I did -
export interface IHistory {
reports: Readonly<{
readonly id?: string,
status?: Status,
readonly created_at?: Date,
}>
}[];
The map I'm doing:
{props.history!.map((index, idx) => {}
The error:
TypeError: Cannot read properties of null (reading 'map')
What am I doing wrong?
I want to display only the reports.
Added -
Interface -
export interface IHistory {
reports: Array<{
id?: string;
status?: Status;
created_at?: string;
}>;
};
const [ hitoryState, setHistoryState ] = useState<IHistory | null>(null);
useEffect(() => {
backendAPIAxios.get('/history')
.then((response: AxiosResponse<IHistoryResponse>) => {
if (!response.data) {
return alert('Failed to get history');
}
setHistoryState(() => response.data);
})
.catch((e: AxiosError) => {
// alert(`Failed to get history with error: ${e}`);
});
}, [setHistoryState])
console.log(props.history!.reports.map((hist) => <p>{hist.created_at}</p>))
This is the error I'm getting:
You are making IHistory an array of reports objects, when reports is the field with the array. Also, created_at will likely be a string and not a date if it's being returned from the backend.
type Status = "fair" | "unfair";
interface IHistory {
reports: Array<{
id?: string;
status?: Status;
created_at?: string;
}>;
};
const backendHistory: IHistory = {
reports: [
{ id: "123", status: "fair", created_at: new Date().toISOString() },
{ id: "456", status: "unfair", created_at: new Date().toISOString() },
]
};
const result = backendHistory.reports.map(({ id }, _idx) => id);
console.log("result", result);
React code:
import React from "react";
type Status = "fair" | "unfair";
interface IHistory {
reports: Array<{
id?: string;
status?: Status;
created_at?: string;
}>;
}
async function fakeFetch(): Promise<IHistory> {
const backendHistory: IHistory = {
reports: [
{ id: "123", status: "fair", created_at: new Date().toISOString() },
{ id: "456", status: "unfair", created_at: new Date().toISOString() }
]
};
return new Promise((resolve) =>
setTimeout(() => resolve(backendHistory), 1000)
);
}
export default function App() {
const [backendHistory, setBackendHistory] = React.useState<IHistory>();
React.useEffect(() => {
let isAlive = true;
(async function () {
const result = await fakeFetch();
if (isAlive) {
setBackendHistory(result);
}
})();
return () => {
isAlive = false;
};
}, []);
return (
<div className="App">
<h1>Backend History</h1>
{backendHistory ? (
backendHistory.reports.map((hist) => <p>{hist.id}</p>)
) : (
<span>loading</span>
)}
</div>
);
}
Started to use fullcalendar and I am trying to make a test to test my event component that gets rendered for an event. The problem I am running into is EventContentArg. I getting typescript errors that my event property is missing a bunch of things that are not really related for the test to render. How can I fix the following error:
Type '{ id: string; start: Date; end: Date; title: string; backgroundColor: string; borderColor: string; editable: boolean; textColor: string; resourceId: string; extendedProps: { type: { id: number; name: string; }; status: { ...; }; displayProperties: { ...; }; }; }' is missing the following properties from type 'EventApi': _context, _def, _instance, setProp, and 26 more.ts(2740)
main.d.ts(1289, 5): The expected type comes from property 'event' which is declared here on type 'EventContentArg'
Here is part of my component
import { EventContentArg } from '#fullcalendar/react';
export const EventContent = (event: EventContentArg) => {
const { backgroundColor, timeText, view } = event,
{ end, extendedProps, start, title } = event.event,
{ displayProperties } = extendedProps,
slotDuration = view.getOption('slotDuration') as ISlotDuration,
slotDurationNumber = Math.floor(slotDuration.milliseconds / 60000),
appointmentLength = end!.getTime() - start!.getTime(),
duration = Math.floor(appointmentLength / 60000);
return (
<div>My Component</div>
)
}
Here is my test
import { render, screen } from '#testing-library/react';
import React from 'react';
import { EventContentArg } from '#fullcalendar/react';
import { EventContent } from '.';
import { events } from '../../actions/mockData';
import { prettyDate } from './EventContent.stories';
test('event renders with all expected data', () => {
let event = events[2];
let timeText = `${prettyDate(event.start)} - ${prettyDate(event.end)}`;
let args: EventContentArg = {
backgroundColor: 'rgb(133,33,51)',
event,
timeText: timeText,
view: {
getOption: () => {
return {
milliseconds: 900000,
};
},
},
};
render(<EventContent {...args} />);
});
Here is the events from the mockData
export const events = [
...,
{
id: '3',
start: new Date(thirdStart),
end: new Date(thirdEnd),
title: 'Hair Coloring', // This would be like the service name
backgroundColor: 'rgb(133,33,51)', // Should be based on event status
borderColor: '#d2d2d2', // For now should be same color as bg
editable: false,
textColor: '#2d2d2d',
resourceId: '2',
extendedProps: {
type: {
id: 1,
name: 'Appointment',
},
status: {
id: 2,
name: 'Scheduled',
},
displayProperties: {
attendeeDetails: 'with Kylo Ren',
resourceDetails: 'Chair 2',
eventIcons: [],
},
},
},
...,
];
I want to pass entire objects of contents in Interface Props to RichText.tsx.
Below is what I tried;
interface Props {
title: string;
contents: {
content: [
{
content: [
{
nodeType: string;
value: string;
}
];
nodeType: string;
data: { key: string };
}
];
};
}
const PostDetail: React.FC<Props> = ({ title, contents }) => {
return (
<PageLayout>
<h1>{title}</h1>
<RichText content={contents} />
</PageLayout>
);
};
The result is that RichText component received the object like this;
{
content: [
{
nodeType: string;
value: string;
}
];
nodeType: string;
data: { key: string };
}
But I want the component to have the object in this style...
{
content: [
{
content: [
{
nodeType: string;
value: string;
}
];
nodeType: string;
data: { key: string };
}
];
}
I thought this was because I specified the key "content" when passing props, so I tried using spread operator to pass the props as shown below.
const PostDetail: React.FC<Props> = ({ title, contents }) => {
return (
<PageLayout>
<h1>{title}</h1>
<RichText {...contents} />
</PageLayout>
);
};
However, I got an error as a result: Object(...) is not a function.
Any idea?
[Edited]
When I console.log(contents) in PostDetail, the result is like this,
Seems like even in contents, the key 'content' already disappears...
I'm trying to move a directory component into redux, but I keep getting this error. The type is basically an array of objects. If I change the type from 'Section' to any, then the sections prop in mapStateToProps complains that 'no overload matches this call'.
Property 'sections' does not exist on type '({ title: string; imageURL: string; id: number; linkURL: string; size?: undefined; } | { title: string; imageURL: string; size: string; id: number; linkURL: string; })[]'
Directory.tsx
import React from 'react';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { selectDirectorySections, Section } from '../../redux/directory/directorySelectors';
import MenuItem, { IMenuItem } from '../menuItem/MenuItem';
import './Directory.scss';
interface IMenuItems extends IMenuItem {
id:number
};
const Directory = ({ sections }:Section) => {
return (
<div className='directory-menu'>
{sections.map(({ id, ...otherSectionProps }:IMenuItems) => (
<MenuItem key={id} {...otherSectionProps} />
))}
</div>
);
};
const mapStateToProps = createStructuredSelector({
sections: selectDirectorySections
});
export default connect(mapStateToProps)(Directory);
directorySelectors.ts
import { RootState } from '../rootReducer';
import { createSelector } from 'reselect';
const selectDirectory = (state:RootState) => state.directory;
export const selectDirectorySections = createSelector(
[selectDirectory],
directory => directory.sections
);
export type Section = ReturnType<typeof selectDirectorySections>;
directoryReducer.js
const INITIAL_STATE = {
sections: [
{
title: 'hats',
imageURL: 'https://i.ibb.co/cvpntL1/hats.png',
id: 1,
linkURL: 'hats'
}...
]
};
const directoryReducer = (state=INITIAL_STATE, action) => {
switch(action.type) {
default:
return state;
};
};
export default directoryReducer;
In this code:
const Directory = ({ sections }:Section) => {
return (
<div className='directory-menu'>
{sections.map(({ id, ...otherSectionProps }:IMenuItems) => (
<MenuItem key={id} {...otherSectionProps} />
))}
</div>
);
};
you're trying to destructure the property sections from an object of type Section. Section is defined as:
export const selectDirectorySections = createSelector(
[selectDirectory],
directory => directory.sections
);
export type Section = ReturnType<typeof selectDirectorySections>;
So it has the type that directory.sections has. From the name directory.sections, and from the error message, that's an array:
Property 'sections' does not exist on type '({ title: string; imageURL: string; id: number; linkURL: string; size?: undefined; } | { title: string; imageURL: string; size: string; id: number; linkURL: string; })[]'
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^
Arrays don't have a sections property (unless you add one, which is usually not a good idea).
You'll need to modify how you define Section, or change your code using it to use it as an array (e.g., by looping, etc.).
I have this component :
interface listvote {
items: any[]
}
const ListVote: React.FC<listvote> = props => {
useEffect(() => {
console.log(items)
})
return (
<VoteResult
id={props.id}
img={props.img}
name={props.name}
score={props.score}
/>
)
}
export default ListVote
It receives this Array as a prop:
<ListVote items={dataListVote} />
const dataListVote = [
{
id: 1,
img:
'sampleimage.com',
name: 'samplename',
score: 50,
},
{
id: 2,
img:
'sampleimage.com',
name: 'samplename',
score: 80,
},
]
There is another component inside ListVote :
interface voteresult {
items: any[]
}
const VoteResult: React.FC<voteresult> = props => {
useEffect(() => {
console.log(props)
})
return <h1>hello</h1>
}
export default VoteResult
The problem is when I try to pass the same array to another component inside ListVote component, it throws this error:
Type 'PropsWithChildren<listvote>' is missing the following properties from type 'any[]': length, pop, push, concat, and 28 more.
Based on your usage:
<VoteResult
id={props.id}
img={props.img}
name={props.name}
score={props.score}
/>
VoteResult does not accept items as a prop. So your type is incorrect:
interface voteresult {
items: any[]
}
Correct Type
The simplest type to get rid of the error:
interface voteresult {
id: any;
img: any;
name: any;
score: any;
}
Home component :
const dataListVote = [
{
id: 1,
img:
'sampleimage.com',
name: 'samplename',
score: 50,
},
{
id: 2,
img:
'sampleimage.com',
name: 'samplename',
score: 80,
},
]
<ListVote items={dataListVote} />
ListVote COmponent:
interface listvote {
items: any[]
}
const ListVote: React.FC<listvote> = props => {
useEffect(() => {
console.log(typeof props)
})
return <VoteResult items={props} />
}
export default ListVote
VoteResult Component :
interface listvote {
items: any[]
}
const VoteResult: React.FC<voteresult> = props => {
useEffect(() => {
console.log(props)
})
return <h1>hello</h1>
}
export default VoteResult
Error :
Type 'PropsWithChildren<listvote>' is missing the following properties from type 'any[]': length, pop, push, concat, and 28 more.