Undefined params in react native navigation - react-navigation

i am trying to pass parameters through navigation
this is the access to ProfileScreen in my DrawerSection
<DrawerItem
icon={({color, size}) => (
<Icon
name="ios-person"
color={color}
size={size}
/>
)}
label="Account"
onPress={() => {props.navigation.navigate('ProfileScreen',{ params: {text: 'test'}})}}
/>
and this is my ProfileScreen
const ProfileScreen = ({route}) => {
console.log(route);
the log then give me this result
{"key": "Account-qkhK3r7vkx", "name": "Account", "params": undefined}
i don't understand what i'm doing wrong here

Could it be that you are trying to access a nested screen?
If so you will have to modify the parameters you pass to the navigate function.
react-native navigation 5 undefined params

Related

AntD: Config Provider API for customization does not allow text customization

I am using AntD Config Provider to provide custom styles to certain AntD components. Been playing with the button component and it seems there is only certain things you can change. I seem unable to change the text color of the button. Has anyone figured out how to do this?
These are the attributes I have tried to change for text color with no success.
Updates:
The button is of Primary type and the Token attribute is not part of the individual component so it can not be used.
Here is what the code looks like
export const SecondaryConfigProvider = (props:any) => {
return (
<ConfigProvider
theme={{
components: {
Button: {
colorText: "orange",
colorPrimaryBg: "red",
colorPrimaryBorder: "red",
colorPrimaryBorderHover: "red",
colorPrimaryHover: "lightgray",
colorPrimary: "blue",
colorPrimaryActive: "lightgray",
colorPrimaryTextHover: "lightgray",
colorPrimaryText: "lightgray",
colorPrimaryTextActive: "lightgray",
colorBgContainer: "blue",
colorBorderBg: "red",
controlOutline: "none"
}
}
}}
>
{props.children}
</ConfigProvider>
)
}
the button layout is here
import {Button, DatePicker} from 'antd'
import { PrimaryConfigProvider } from "./PrimaryConfigProvider"
import { SecondaryConfigProvider } from "./SecondaryConfigProvider"
export const TestingConfig = () => {
return (
<>
<PrimaryConfigProvider>
<Button type="primary">Primary Button</Button>
</PrimaryConfigProvider>
<SecondaryConfigProvider>
<Button type="primary">Secondary Button</Button>
</SecondaryConfigProvider>
</>
)
}
App.jsx -- contains <TestingConfig/>
Index.js
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
If you will go to definition of some Button's token (right click on token then go to definition, or hover token and press F12, or ctrl+click) - you'll be able to see the whole list of them.
Button: {
//others token: value ...
colorPrimary: 'red',
},
If it doesn't help you can I see how do you use <Button /> in your code? As I can see your screenshot your tokens are defined for primary button, so you need to pass props to your button component as below:
<Button type="primary"> I am a button <Button />

React Native Stack Navigator passing props

I want to pass some props (value) to another page and I'm using stackNavigator
App.js:
import Insert from "./components/pages/Insert";
import ViewData from "./components/pages/ViewData";
const Stack = createStackNavigator();
NavigationContainer>
<Stack.Navigator headerMode={false}>
<Stack.Screen name="Insert Your data" component={Insert} />
<Stack.Screen name="ViewData" component={ViewData} />
</Stack.Navigator>
</NavigationContainer>
Insert.js
const Insert = ({ props, navigation: { navigate } }) => {
const [enteredName, setEnteredName] = useState();
const [enteredSurname, setEnteredSurname] = useState();
const sendValues = (enteredName, enteredSurname) => {
setEnteredName(enteredName);
setEnteredSurname(enteredSurname);
navigate("ViewData", {
name: enteredSurname,
surname: enteredSurname
});
};
...
<View>
<Button
title="Submit"
onPress={() => sendValues(enteredName, enteredSurname)}
/>
ViewData.js
const ViewData = ({props, navigation: { goBack } }) => {
let name = enteredName;
console.log(name); /// I always get undefined
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Text>Here {name}</Text>
<Button onPress={() => goBack()} title="Edit Data" />
</View>
);
};
When I Submit I'm always getting undefined into the console.
For sure I'm mistaking somewhere.
Any idea?
Thanks!!
Refer to https://reactnavigation.org/docs/hello-react-navigation/#passing-additional-props
Use a render callback for the screen instead of specifying a component
prop:
<Stack.Screen name="Home">
{props => <HomeScreen {...props} extraData={someData} />}
</Stack.Screen>
You can change like this
import Insert from "./components/pages/Insert";
import ViewData from "./components/pages/ViewData";
const Stack = createStackNavigator();
<NavigationContainer>
<Stack.Navigator headerMode={false}>
<Stack.Screen name="Insert Your data">
{props => (<Insert {...props} extraData={data}/>)}
<Stack.Screen name="ViewData" component={ViewData} />
</Stack.Navigator>
</NavigationContainer>
Reading your code it seems that you want to pass some params to the render component when navigate.
Refer to https://reactnavigation.org/docs/route-prop , the params from
navigation.navigate(routeName, params)
are passed to the screen render component as propriety of the route object. So in your case it should work:
let name = props.route.params.name;

Edit without passing id as identifier

Suppose I have a List and and Edit of items of the following schema:
STRING key UNIQUE PRIMARY
STRING value
The problem is that when using admin-on-rest, the Edit uses the id by default to generate the request, if it does not have one, it passes undefined. How can I change that on the SimpleForm so it uses another parameter instead of id - in my case, key -.
Example of the List and Edit:
export const ParamList = props => (
<List title = "All params" { ...props} >
<Datagrid >
<TextField source = "key" sortable={false} />
<TextField source = "value" sortable={false} />
<EditButton />
</Datagrid>
</List>
);
export const ParamEdit = props => (
<Edit title = {< ParamTitle />} { ...props } >
<SimpleForm >
<TextInput source = "key" />
<TextInput source = "value" />
</SimpleForm>
</Edit >
);
When I send the editing, the following request is made:
PUT www.randomurl.com/param/undefined
But i wished it was something like:
PUT www.randomurl.com/param/<item's key>
I have seen that on the documentation that is possible to set customize the requests as a whole. But was thinking if there is something easier, like adding a parameter on SimpleForm:
export const ParamEdit = props => (
<Edit title = {< ParamTitle />} { ...props } >
<SimpleForm id={"key"}>
<TextInput source = "key" />
<TextInput source = "value" />
</SimpleForm>
</Edit >
);
Thanks in advance.
As explained in the documentation, the correct and only way to do that is to write a custom restClient. See https://marmelab.com/admin-on-rest/FAQ.html#can-i-have-custom-identifiersprimary-keys-for-my-resources

Easy way to add a drawer item with custom onPress?

I'm using DrawerNavigator and, as long as I want to navigate to a new screen, all's fine.
Now I want to add a drawer item which does not navigate to a new screen but simply triggers an action (in general). Specifically, I want to use 'react-native' Share functionality.
I got this to work but I think the solution is not a very good one. Here's what I got so far:
const myContentComponent = props => (
<ScrollView alwaysBounceVertical={false}>
<SafeAreaView style={{ flex: 1 }} forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerItems {...props} />
<TouchableItem
key="share"
onPress={() => {
Share.share(
{
message: 'YO: this will be the text message',
url: 'http://tmp.com',
title: 'This will be the email title/subject',
},
{
// Android only:
dialogTitle: 'This will be the title in the dialog to choose means of sharing',
},
);
props.navigation.navigate('DrawerClose');
}}
delayPressIn={0}
>
<SafeAreaView forceInset={{ left: 'always', right: 'never', vertical: 'never' }}>
<View style={[{ flexDirection: 'row', alignItems: 'center' }, {}]}>
<View style={[{ marginHorizontal: 16, width: 24, alignItems: 'center' }, { opacity: 0.62 }, {}]}>
<Icon name="share" />
</View>
<Text style={[{ margin: 16, fontWeight: 'bold' }, { color: DrawerItems.defaultProps.inactiveTintColor }]}>Share</Text>
</View>
</SafeAreaView>
</TouchableItem>
</SafeAreaView>
</ScrollView>
);
const RootStack = DrawerNavigator(
{
Settings: {
screen: SettingsScreen,
},
},
{
contentComponent: myContentComponent,
},
);
Basically, I am creating a new contentComponent based off of the default:
https://github.com/react-navigation/react-navigation/blob/v1.5.8/src/navigators/DrawerNavigator.js#L16-L22
I am copying the styles and element structure of a normal drawer item (everything under TouchableItem) - all this so I can define my own onPress which does the share logic and closes the drawer.
There has to be a better way right? What happens if I want the "Share" drawer item somewhere amongst the drawer items rendered by DrawerItems (the ones that support navigation)? Right now I can only work around the items rendered by DrawerItems. Besides, copying so much code from react-navigation seems like really bad form.
I just want an item which does some custom logic instead of rendering a screen.
I am not sure will it be helpful?
I used onPress event for logout like this way. It's no need to render a new DrawerItems
const DrawerNavigator = createAppContainer(createDrawerNavigator({
Logout: {
screen: EmptyScreenForLogoutConfirmation,
navigationOptions: ({ navigation }) => ({
tabBarLabel: 'Logout',
drawerIcon: ({ tintColor }) => <Icon name={"ios-cog"} size={26} />,
}),
},
},
{
contentComponent:(props ) => (
<DrawerItems {...props}
onItemPress = {
( route ) =>
{
if (route.route.routeName !== "Logout") {
props.onItemPress(route);
return;
}
return Alert.alert( // Shows up the alert without redirecting anywhere
'Confirmation required'
,'Do you really want to logout?'
,[
{text: 'No'},
{text: 'Yes', onPress: () => { props.navigation.navigate('Logedout'); }},
]
)
}
}
/>
),
contentOptions: {
activeTintColor: '#e91e63',
}
},))

Admin on Rest onClick being called on render and not on click

The issue I am having is I have a button:
const LogActions = ({ resource, filters, displayedFilters, filterValues, basePath, showFilter, refresh, record }) => (
<CardActions style={cardActionStyle}>
<RaisedButton primary label="Cancel" onClick={HandleClick(record["id"])} />/>
</CardActions>
);
This button is used in a List like so:
export const LogList = (props) => (
<List {...props} perPage={100} title="Logs and Reports" filters={< FileFilter/>}>
<Datagrid>
<TextField source="inputfile" label="Input File" />
<TextField source="cycle" label="Cycle" />
<TextField source="job" label="Job" />
<TextField source="name" label="File Name" />
<ShowButton/>
<LogActions/>
</Datagrid>
</List>
);
This is the HandleClick:
const HandleClick = (id) => {
fetch(`controller_service/archivedfiles/${id}`, { method: 'GET', body:{} })
.then(() => {
// do stuff
})
.catch((e) => {
console.error(e);
//error
});
}
Okay so my problem is that whenever I go to this page, it will create the datagrid, but while the button is being rendered it calls HandleClick which then fetches that data before I even click on the button, and when I click on the button nothing happens. Can someone explain what I am doing wrong?
As wesley6j said, the function gets called when you assign it with parameters.
A way to avoid this is to use .bind(this,params) or wrap your HandleClick in another function like this:
onClick={() => HandleClick(record["id"])}

Resources