what version of payload are you on?
"payload": "^1.11.4",
interesting, works for me
want to share your users collection here again?
import { CollectionConfig } from 'payload/types';
const Users: CollectionConfig = {
slug: 'users',
admin: {
useAsTitle: 'email',
disableDuplicate: true,
},
fields: [
{
label: 'Password history',
name: 'passwordHistory',
type: 'array',
admin: {
initCollapsed: true,
components: {
RowLabel: RowLabel,
},
condition: (_, siblingData) => {
return siblingData.passwordHistory && siblingData.passwordHistory.length > 0;
},
},
access: {
create: () => false,
update: () => false,
read: userHasUserManagerRole,
},
fields: [
{
name: 'password',
type: 'text',
label: 'Password',
hidden: true,
},
{
name: 'updatedAt',
type: 'text',
label: 'Updated at',
hidden: true,
},
{
name: 'updatedBy',
type: 'text',
label: 'Updated by',
hidden: true,
},
{
name: 'userSnapshot',
type: 'textarea',
label: 'User snapshot',
hidden: true,
},
],
},
],
hooks: {
beforeOperation: [checkPasswordStrength],
beforeValidate: [storePasswordHistory],
},
};
export default Users;
RowLabel:
`
const RowLabel: React.FC<{ data: any, index: number }> = ({ data, index }) => {
const checkIsCompactView = width => (width <= 1572 && width >= 1024) || width <= 690;
const [isCompactView, setIsCompactView] = useState(checkIsCompactView(window.innerWidth));
useEffect(() => {
const handleResize = () => {
setIsCompactView(checkIsCompactView(window.innerWidth));
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
if (isCompactView) {
return (
<CompactRowLabelWrapper>
<EditLabel>Edited:</EditLabel>
<CompactP>
{data.updatedAt} by {data.updatedBy}
</CompactP>
</CompactRowLabelWrapper>
);
} else {
return (
<RowLabelWrapper>
<Index>
<P>Index:</P>
<DataItem>{index}</DataItem>
</Index>
<UpdatedOn>
<P>Updated on:</P>
<DataItem>{data.updatedAt}</DataItem>
</UpdatedOn>
<UpdatedBy>
<P>Updated by:</P>
<DataItem>{data.updatedBy}</DataItem>
</UpdatedBy>
</RowLabelWrapper>
);
}
};
Even using the supplied
RowLabel
example in the docs - the TS error would flag up as well so I don't think it's to do w/ my custom component
The one in the docs should show how to import
RowLabelArgs
but does not. Here is how you should type your custom component:
import { RowLabelArgs } from 'payload/dist/admin/components/forms/RowLabel/types';
import * as React from 'react';
export const RowLabelComponent: React.FC<RowLabelArgs> = ({ data, index }) => (
<div>custom row label</div>
);
We should make the import better for the row label args and update the docs.
But I still was unable to repro the error message you are getting. Maybe try removing your yarn lock and node modules and re-run
yarn
Thanks
@281120856527077378- spinning a fresh deployment 🤞
I'll action your recommendations as well re
yarn.lock
I'm getting TS error in the same place as well, no matter how I type my custom RowLabel component. I currently have the exact same type you suggested:
import { RowLabelArgs } from "payload/dist/admin/components/forms/RowLabel/types";
const AnswerRowLabel: React.FC<RowLabelArgs> = ({ data, index }) => {
which returns either the default string or a custom React component.
I've already removed my node_modules and reinstalled the dependencies, but still get the following error when I try to build (no error on VSCode though):
src/admin/components/AnswerRowLabel.tsx:14:7 - error TS2322: Type '({ data, index }: RowLabelArgs) => string | Element' is not assignable to type 'FC<RowLabelArgs>'.
Type 'string | Element' is not assignable to type 'ReactElement<any, any>'.
Type 'string' is not assignable to type 'ReactElement<any, any>'.
am I missing something? :/
(I'm on Payload 1.15.6)
I think you can just wrap your string label in a fragment, i.e.
return <>{label}</>
but when I return a string I don't get any errors, only when I return JSX.
You mean, when using a function and returning a string right?
is a string a valid return type from a React component?
this is what I had for the
RowLabel
component:
function AnswerRowLabel({ data, index }: RowLabelArgs) {
if (!data?.answerText) {
return `Answer ${index}`;
}
const status = data.isCorrect ? "✅" : "🚫";
return (
<div style={{ display: "flex", gap: "8px", alignItems: "center" }}>
<span>{status}</span> <span>{data.answerText}</span>
</div>
);
}
but I had to change the second return to just a regular string
${status} ${data.answerText}
to avoid the TS error on build.
You could make it this instead:
function AnswerRowLabel({ data, index }: RowLabelArgs) {
if (!data?.answerText) {
return <React.Fragment>Answer {index}</React.Fragment>;
}
const status = data.isCorrect ? "✅" : "🚫";
return (
<div style={{ display: "flex", gap: "8px", alignItems: "center" }}>
<span>{status}</span> <span>{data.answerText}</span>
</div>
);
}
a-ha, that works. but string is a valid
ReactNode
, so I wouldn't expect to have to add a fragment around it. 🤔
export type RowLabelFunction = (args: RowLabelArgs) => string;
export type RowLabelComponent = React.ComponentType<RowLabelArgs>;
maybe these types could be combined into one:
export type RowLabelComponent = (args: RowLabelArgs) => React.ReactNode;
Star
Discord
online
Get dedicated engineering support directly from the Payload team.