Can't customise user menu in react-admin - react-admin

I'm trying to customise the user menu in react-admin and I've followed the instructions and the example inside the react-admin repo but I'm still getting this error:
Type '{ ref: ForwardedRef<any>; to: string; primaryText: string; leftIcon: Element; onClick: any; sidebarIsOpen: true; }' is missing the following properties from type 'Pick<any, "selected" | "dense" | "className" | "style" | "classes" | "innerRef" | "button" | "slot" | "title" | "key" | "value" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | ... 277 more ... | "ContainerProps">': selected, dense, className, style, and 283 more. TS2740
Here's my code.
import SettingsIcon from '#material-ui/icons/Settings';
import { forwardRef } from 'react';
const ConfigurationMenu = forwardRef<any, any>((props, ref) => (
<MenuItemLink
ref={ref}
to="/metamaskLogin"
primaryText="MetaMask"
leftIcon={<SettingsIcon />}
// onClick={onClick} // close the menu on click
// dense={true}
onClick={props.onClick}
sidebarIsOpen
/>
));
const MyUserMenu = (props: any) => (
<UserMenu {...props}>
<ConfigurationMenu />
</UserMenu>
);
export const MyAppBar = (props: any) => <AppBar {...props} userMenu={<MyUserMenu />} />;
I've tested I can hide the user menu by setting userMenu={false}
the example code can be found here: https://github.com/marmelab/react-admin/blob/master/examples/demo/src/layout/AppBar.tsx

figured it out, just needed to add {...props} to MenuItemLink

Related

react-admin label prop does not work when creating custom fields

I have created a simple wrapper component for ReferenceField in react-admin app:
import {FC} from "react";
import {ReferenceField, ReferenceFieldProps} from "react-admin";
export const UserReference: FC<Omit<ReferenceFieldProps, "reference" | "label">> = (props) => {
return <ReferenceField {...props} label="User" reference="users" />;
};
UserReference.displayName = "UserReference";
But when using the field the label is still inferred from source property (which is the default).
When I directly use ReferenceField with label it works:
// UserReference renders label "User id" and ReferenceField renders correct "User"
<Datagrid>
<UserReference source="user.id" />
<ReferenceField reference="users" label="User" source="user.id" />
</Datagrid>
Why does this happen and how can I fix it?
Do I have to forward refs?
<Datagrid> inspects its children label prop to build the header row. So to make it work in your case, you have to define the label in the defaultProps:
import {FC} from "react";
import {ReferenceField, ReferenceFieldProps} from "react-admin";
export const UserReference: FC<Omit<ReferenceFieldProps, "reference" | "label">> = (props) => {
return <ReferenceField {...props} reference="users" />;
};
UserReference.displayName = "UserReference";
UserReference.defaultProps = { label: 'User' };
this is documented in the react-admin documentation: https://marmelab.com/react-admin/Fields.html#writing-your-own-field-component

How to press a next button and focus another text field input?

Version react hook form
^7.27.0
What I tried to follow and without successful
react hook form - Discussions 7818
react hook form - Issues 230
About what I have
I have 4 text field components at my screen, the name of each text field is name, documentation, email, password and I would like to know how can I setup some configuration that it will be pressed the NEXT button at keyboard and will focus the following text fields?
An example that I have inside at my component file, again I would like to press the next button and the next component that I will config, will be focus.
<TextField
name="name"
label={I18n.t('registerPersonal.fullNameLabel')}
placeholder={I18n.t('registerPersonal.fullNameInput')}
icon={<TypographyIcon fill={!!errors.name && theme.colors.attention} />}
error={errors.name?.message}
errors={errors}
control={control}
returnKeyType="next"
/>
<TextField
name="documentation"
label={I18n.t('registerPersonal.documentIdentificationLabel')}
placeholder={I18n.t('registerPersonal.documentIdentificationInput')}
icon={
<DocumentIcon
fill={!!errors.documentation && theme.colors.attention}
/>
}
error={errors.documentation?.message}
control={control}
returnKeyType="next"
/>
Some properties that I get at my personal hook
const {
control,
handleSubmit,
formState: { errors, isValid }
} = useForm({ resolver: yupResolver(schema) })
My component TextField
import { TextInputProps, Text } from 'react-native'
import { Control, useController } from 'react-hook-form'
import { Container, Wrapper, TextInput, Label } from './styles'
import theme from '../../global/styles/theme'
type TextFieldProps = {
placeholder?: string
label?: string
icon?: React.ReactNode
error?: string
errors?: {
[x: string]: any
}
name: string
control: Control
} & TextInputProps
export function TextField(props: TextFieldProps) {
const { placeholder, label, icon, error, errors, name, control, ...rest } =
props
const { field } = useController({
control,
defaultValue: '',
name
})
return (
<>
<Container>
{!!label && <Label>{label}</Label>}
<Wrapper hasLabel={!!label} hasError={!!error}>
{!!icon && icon}
<TextInput
value={field.value}
onChangeText={field.onChange}
placeholder={error ? error : placeholder}
placeholderTextColor={
error ? theme.colors.attention : theme.colors.grayColor
}
{...rest}
/>
</Wrapper>
{errors && errors.name && errors.name.type === 'matches' && (
<Text>{errors.name.message}</Text>
)}
</Container>
</>
)
}
your component must include ref prop like
<TextInput
ref={inputRef} // this one
value={field.value}
onChangeText={field.onChange}
placeholder={error ? error : placeholder}
placeholderTextColor={
error ? theme.colors.attention : theme.colors.grayColor
}
{...rest}
/>
then, you need to create ref from parent for each field
const emailRef = useRef(null);
const passwordRef = useRef(null);
after this, you need to add the props that is
onSubmitEditing={() => passwordRef.current.focus()} // to auto focus password field
finally,
<TextField
onSubmitEditing={() => passwordRef.current.focus()} // here
name="name"
label={I18n.t('registerPersonal.fullNameLabel')}
placeholder={I18n.t('registerPersonal.fullNameInput')}
icon={<TypographyIcon fill={!!errors.name && theme.colors.attention} />}
error={errors.name?.message}
errors={errors}
control={control}
returnKeyType="next"
/>

set React Native state to the Button title prop

I can't figure out how to update the state in my basic React Native application to equal whatever is in the title prop of the Button.
I've tried just setting the state to be {title} and that hasn't worked. I am using the useState hook so I don't think I should need to use "this.".
import React, {useState} from 'react';
import { View, Text, Button } from 'react-native';
const StarterForm = () => {
const [formStage, setFormStage] = useState(1)
const [feelings, setFeelings] = useState('')
console.log(feelings)
const updateFormStage = () => {
setFormStage(formStage + 1)
setFeelings({title})
}
switch (formStage) {
case 1:
return (
<View>
<Text>How are you?</Text>
<Button title="Excellent" onPress={updateFormStage}/>
</View>
)
case 2:
return (
<Text>This is the case of two</Text>
)
}
};
In the example, I expect console.log(feelings) to equal "Excellent" once the button has been pressed.
You can use ref for that, but I think the best way to solve your problem is store "Excellent" in a variable, and use onPress={() => updateFormStage(mVariable)}
One way would be setting reference for your defined button and after click on it, retrieve data from reference like this:
<Button ref={ref => { this.button = ref; }}
title="Excellent"
onPress={this.updateFormStage} />
You can access your title via button reference using this.button.title:
updateFormStage = () => {
console.log(this.button.title);
}

Pivot: Start with no tabs selected

Using Fabric React, I am working on a component that uses the Pivot element.
When the component is first shown, no tabs should be selected, and some content must be shown under the tab headers. Once a tab is clicked, related content will be shown there.
The example "No Pivots Selected" in the documentation page is pretty close to what I want. In the first render, no tabs are selected. I am thinking that the prop selectedKey={null} should give that result.
Following code is based on that example, yet even when the component is shown first time, a tab (first one) is shown as selected (e.g. there is a blue underline under it).
What is the problem?
import * as React from "react";
import { Pivot, PivotItem } from "office-ui-fabric-react";
export interface MainProps {}
export const Main: React.FC<MainProps> = () => {
const [selectedKey, setSelectedKey] = React.useState(null);
const pivotItems: { [key: string]: React.ReactElement<any> } = {
Settings: <div>Settings</div>,
Controls: <div>Controls</div>
};
const _getTabId = (itemKey: string): string => {
return `ShapeColorPivot_${itemKey}`;
};
const _handleLinkClick = (item: PivotItem): void => {
setSelectedKey(item.props.itemKey);
};
return (
<>
<Pivot
headersOnly
selectedKey={selectedKey}
getTabId={_getTabId}
onLinkClick={_handleLinkClick}
style={{ flexGrow: 1 }}
>
{Object.keys(pivotItems).map(name => (
<PivotItem
key={`pivotItemKey_${name}`}
headerText={name}
itemKey={name}
/>
))}
</Pivot>
{selectedKey ? pivotItems[selectedKey] : <div>Start</div>}
</>
);
};
I did a quick codepen using
<Pivot selectedKey={null} >
and it worked just fine. Are you sure you're on the most recent version of Fabric?

Text and TouchableOpacity Style Type Annotations

I am trying to type annotate my React Native project using Flow, but I am having trouble finding the type definitions for the Text and TouchableOpacity elements so I can reference their style prop type definitions. How can I import and/or reference the type definitions for these elements?
Code below:
// #flow
import * as React from "react";
import { Text, TouchableOpacity } from "react-native";
type Props = {
segmentIndex: number,
segmentInfo: {
title: string
},
segmentStyle: ???, // WHAT SHOULD I USE HERE?
titleStyle: ???, // WHAT SHOULD I USE HERE?
onSelection: (number) => void
}
export const SegmentButton = (props: Props) => {
const _segmentPressed = () => {
props.onSelection(props.segmentIndex)
}
return (
<TouchableOpacity style={props.segmentStyle} onPress={_segmentPressed}>
<Text style={props.titleStyle}>{props.segmentInfo.title.charAt(0).toUpperCase() + props.segmentInfo.title.substring(1)}</Text>
</TouchableOpacity>
)
}
There are many ways to define StyleSheet type.
1. react-native generic way
reference from react-native library,
SwipeableQuickActionButton.js
import { View } from 'react-native';
type Prop = {
style?: ?View.propTypes.style,
}
2. react-navigation generic way
reference from react-navigation library,
TypeDefinition.js
export type Style =
| { [key: string]: any }
| number
| false
| null
| void
| Array<Style>;
If you already installed react-navigation, import it from:
import type { Style } from 'react-navigation/src/TypeDefinition';
type Prop = {
style?: Style,
}
Or you can still use it by define in your own file.
3. make Style type specific for <Text /> and <TouchableOpacity />
It would be the hard way -- although doable, see if that worth the trouble.
take <Picker /> for reference, it defined itemStyle for <Text /> like below, which corresponding to text style for each picker item.
var StyleSheetPropType = require('StyleSheetPropType');
var TextStylePropTypes = require('TextStylePropTypes');
var TextStyle = StyleSheetPropType(TextStylePropTypes);
type Prop = {
itemStyle: TextStyle
}
To use it in your own library, import them from:
import TextStylePropTypes from 'react-native/Libraries/Text/TextStylePropTypes';
import StyleSheetPropType from 'react-native/Libraries/StyleSheet/StyleSheetPropType';
let TextStyle = StyleSheetPropType(TextStylePropTypes);
type Prop = {
style?: ?TextStyle,
}