Null Screen in React Navigation v5? - react-navigation

In React navigation v4 we pass the null screen like this:
`Screen: {
screen: () => null,
navigationOptions: {
tabBarIcon: <AddButton />
}
},`
But How to I can do it in react navigation 5?

I choose this path for the screens I want to hide. May be help you. I manage isLogin with Mobx.
{MenuStore.isLogin ? <></>
: <Drawer.Screen
name="Login"
component={LoginStackScreen}
/>

You can pass <NavigatorName.Screen name="ScreenName">{() => null}</NavigatorName.Screen> to pass null as a screen.

You can use event listener on the tab bar
<Tab.Screen
name="Plus"
component={Add}
listeners={{
tabPress: (e) => {
e.preventDefault(); // — > the main part
},
}}
/>
Where Add is
const Add = () => { return null; };

Related

React Navigation 6 attempting to pass different params to same screen

I currently have the following setup an onboarding stack component:
export default function OnboardingStack(props) {
const { auth, activeUser } = useContext(FirebaseContext);
return (
<Stack.Navigator mode="card" headerMode="none">
<Stack.Screen
name="Login"
component={Login}
option={{
headerTransparent: true
}}
/>
<Stack.Screen name="App" component={AppStack} />
</Stack.Navigator>
);
}
Then I can call a component called MemberList which contains a touchable opacity:
<TouchableOpacity style={styles.touchableRow} onPress={ () => navigateMember(item) }>
the method navigateMember I navigate to "Add Member"
const navigateMember = (item) => {
navigation.navigate("Add Member", {
screen: "Member",
params: {
uid: item,
}
}
);
}
Here item is different each time I click it but when I get into the "Member" screen it retains the first original passed uid. Member component contains:
useEffect(() => {
navigation.addListener('focus', () => {
// console.log(navigation);
console.log('this member route');
console.log(route);
})
navigation.addListener('blur', () => {
console.log('leaving blur');
navigation.setParams({
key: route.key,
params: { uid: 'og' },
})
})
}, [])
Each time the uid remains the same. I've tried to reset it when it blurs but it always retains the same params. Any idea what I'm doing wrong?
The solution was to use push as opposed to navigate.
onPress={() => navigation.push('Member')}
More details found in the documentation

React navigation Tab in Stack with button in Header

I'd like to have a TabNavigator embedded in a StackNavigator with a button in the Header used to navigate in the main Stack.
Here is a snack of my issue: https://snack.expo.io/#guigui64/tabs-in-stack
The propblem is when I create the TabNavigator:
const TabNavigator = createMaterialTopTabNavigator(
{
ScreenA,
ScreenB,
},
{
navigationOptions: {
headerTitle: 'Title when in tab',
headerRight: (
<Button
onPress={() => this.props.navigation.navigate('C')} // here is the issue !
title="ScreenC"
/>
),
},
}
);
I also tried creating a Component with static navigationOptions and have render() return a TabNavigator. In this case, the header appears fine but not the tabs.
Thanks in advance !

admin on rest send extra params to rest call

i have upload button inside create form, on button click handler i will upload image to cloud and on upload success i get image url. i need to pass this image url to rest api. this is my sample code.
When i submit my form i need to send image url as parameter.
Can anyone help me.
Here is my code:
<SimpleForm label="Create Artist">
<TextInput source="name" label="Name" />
<FlatButton style={styles.button} label="Upload Image" primary onClick={this.handleClick} />
</SimpleForm>
this.handleClick = () => {
cloudinary.openUploadWidget({
cloud_name: 'demo',
upload_preset: 'sh3432',
cropping: 'server'
}, function(error, result) {
return result;
});
};
You'll have to implement a custom input for that.
Something like (haven't tested it):
class UploadPictureInput extends Component {
handleClick = () => {
cloudinary.openUploadWidget({
cloud_name: 'demo',
upload_preset: 'sh3432',
cropping: 'server'
}, (error, result) => {
this.props.input.onChange(result);
});
}
render() {
return (
<FlatButton
style={styles.button}
label="Upload Image"
primary
onClick={this.handleClick}
/>
);
}
}
And use this input in your form.

How to show and hide activityindicator from actions in react native redux?

I want to show progress/activityindicator whenever I make an api call from my app, But I can't find the correct solution for this. I can show the activityindicator but I can't hide it from view. Here is my code:
StatusModal.js
constructor(props) {
super(props)
// set state with passed in props
this.state = {
message: props.error,
hide: props.hide,
animating: props.animating
}
}
render() {
if(this.state.animating){
return(
<ActivityIndicator
animating={true}
size="small"
/>
)
}else{
return(
<View>
</View>
)
}
}
and here is how I change the animating state
//show activity
Actions.statusModal({animating: true})
//hide activity
Actions.statusModal({animating: false})
and here is my scene structure:
<Scene key="modal" component={Modal} >
<Scene key="root">
<Scene key='login' component={Login} title='Login Page' hideNavBar={true} />
</Scene>
<Scene key="statusModal" component={StatusModal} />
</Scene>
How can I hide the activity indicator from actions?
It's pretty common thing for applications to handle loading.
The simplest way to handle it is create a separate reducer for this.
E.g.:
function appStateReducer(state = { loading: false }, action) {
switch(action.type) {
case "SET_LOADING":
return { loading: action.payload };
default:
return { loading: false };
}
}
...
const rootReducer = combineReducer(
...otherReducers,
app: appStateReducer
);
...
Later you can use it in your components.
...
const mapStateToProps = (state) => ({
loading: state.app.loading,
});
#connect(mapStateToProps)
class MyScene extends Component {
...
render() {
const { loading } = this.props;
if (loading) {
return (
);
}
return ;
}
Dispatch action SET_LOADING in the start of query with true and dispatch SET_LOADING with false in the end or in case of error.
But one single state for handling loading isn't enough for big application. For example: you need to handle parallel queries to API and to show loader for every single query. Then you'll need such fields in other reducers.
By the way, you'll definitely meet the issue with async flow. I would recommend such middlewares as redux-thunk, redux-saga and redux-observable.
My favourite one is redux-saga. It's a very powerful way to control your async flow and all other side effects in your application.
I hope it helps.

React Material-UI dropdown menu not working

I am creating a simple icon drop-down menu using Material UI. But after rendering the glyph appears and no MenuItems are shown after clicking on the it. Here is the code -
import { IconMenu, IconButton } from 'material-ui' ;
const MoreVertIcon = require('material-ui/lib/svg-icons/navigation/more-vert');
const MenuItem = require('material-ui/lib/menus/menu-item');
const PostCard = React.createClass({
render: function() {
let button = (
<IconButton
touch={true}
tooltip='Click to see menu.'
tooltipPosition='bottom-left'>
<MoreVertIcon />
</IconButton>
);
return (
<IconMenu iconButtonElement={button}>
<MenuItem primaryText="Refresh" />
<MenuItem primaryText="Send feedback" />
<MenuItem primaryText="Settings" />
<MenuItem primaryText="Help" />
<MenuItem primaryText="Sign out" />
</IconMenu>
);
}
});
I had a similar issue. Solution was to to add this somewhere in the app. I'm not sure if it matters where but I added it at a higher-level as possible:
var injectTapEventPlugin = require("react-tap-event-plugin");
injectTapEventPlugin();
Just wanted to add the reason to add injectTapEventPlugin.
According to 300ms tap delay, gone away By Jake Archibald
Browsers stopped waiting 300ms for double taps and react's onClick doesnt give us the proper handle.
and According to react-tap-event-plugin git page
Facebook is not planning on supporting tap events (#436) because browsers are fixing/removing the click delay. Unfortunately it will take a lot of time before all mobile browsers (including iOS' UIWebView) will and can be updated.
Thats why we need to inject the plugin.
About the proper solution, I decided to add the package and inject it in the App's constructor (The higer level I have).
The import:
import injectTapEventPlugin from 'react-tap-event-plugin';
And inside the constructor:
injectTapEventPlugin();
In my case I have to add injectTapEventPlugin as well as change handler.
var injectTapEventPlugin = require("react-tap-event-plugin");
const DropDownMenu = require('material-ui/lib/drop-down-menu');
...
injectTapEventPlugin(); // in constructor
...
handleChange(event, selectedIndex, menuItem) {
this.setState({menu: event.target.value });
}
...
// in render
let menuItems = [
{ payload: '0', text: 'Mon - Sun' },
{ payload: '1', text: 'Mon - Sat' },
{ payload: '2', text: 'Mon - Fri' },
{ payload: '3', text: 'Mon - Fri / Mon - Thu' },
];
...
// in render return
<DropDownMenu menuItems={menuItems} selectedIndex={this.state.menu} onChange={this.handleChange} />

Resources