Not work TransitionPresets. react-navigation version 6 - react-navigation

I recently upgraded from v4 to v6.
As a result, TransitionPresets seems to have stopped working.
<Stack.Screen
name="Home"
component={Home}
options={{ ...TransitionPresets.ModalSlideFromBottomIOS }}
/>
I don't think there is any wrong way to use it.
https://reactnavigation.org/docs/stack-navigator/#transitionpresets
Has anyone else encountered a similar problem?
Edit 2021-11-17
I'm sorry.
I guess I did not understand the difference between native stack and stack.
I used the normal stack and it worked.

I got the same problem, when switching versions and editing a way of writing Stack I noticed that they redirected to different libs.
Change from:
import { createNativeStackNavigator, TransitionPresets } from '#react-navigation/native-stack';
For:
import { createStackNavigator, TransitionPresets, } from '#react-navigation/stack';
And also edited when creating the Stack of:
const Stack = createNativeStackNavigator();
For:
const Stack = createStackNavigator();

In navigation v6
<Stack.Navigator
screenOptions={{
animation: 'fade_from_bottom',
}}>
</Stack.Navigator>
animation options should be :
StackAnimationTypes = 'default' | 'fade' | 'fade_from_bottom' | 'flip' | 'none' | 'simple_push' | 'slide_from_bottom' | 'slide_from_right' | 'slide_from_left'

You need to add TransitionPresets in screenOptions props in Stack.Navigator. Just put same as follows.
<Stack.Navigator screenOptions={{...TransitionPresets.SlideFromRightIOS}}>
<Stack.Screen name="screenName" component={screenComponent} />
</Stack.Navigator>

Related

React routing - react-router-dom pushState() call to history happens too many times

I am using react-router-dom (v6) and noticed that I cannot use the browsers back button as expected. It seems like my application (using react/redux) pushes the location multiple times to the browser history when I am routing to a different location in my app.
This results in an application crash in Safari too:
SecurityError: Attempt to use history.pushState() more than 100 times per 30 seconds
The code looks something like this:
App.tsx
...
<BrowserRouter>
<Routes>
<Route path={ROUTES.auth.login} element={<PublicRoute component={Login} />} />
<Route path={ROUTES.auth.register} element={<PublicRoute component={Register} />} />
<Route path={ROUTES.dashboard} element={<PrivateRoute component={Dashboard} />} />
</Routes>
</BrowserRouter>
...
PublicRoute.tsx
...
export default function PublicRoute({ propsForComponent = {}, ...props }: PublicRouteProps): ReactElement {
const { showLoadingScreen } = useSelector((state: RootState) => ({
showLoadingScreen: state.loading.showLoadingScreen,
}));
const { component: Component } = props;
if (showLoadingScreen) return <LoadingOverlay />;
return <Component {...propsForComponent} />;
}
...
I found out that the PublicRoute component gets called multiple times due to the connection to the redux store with the useSelector hook.
showLoadingScreen gets updated when the application is trying to fetch the user, during this time this variable changes.
So my question is now: how do I prevent multiple re-renders, which causes the history.pushState() calls?
I know I could move the LoadingOverlay component to a different entry point. But In PrivateRoute I am also connected to the redux state because I need to access the user object. (I used the PublicRoute component to show a minimal example of whats going on...)
Any help would be highly appreciated,
cheers!

How do you conditionally display component with ion-segment in Ionic 4 - React

I'd like to have a Registration/Login component that can be switched between by using ion-segment. It's straightforward with ReactJS, but I don't know how to do it with the TypeScript version of React. How do you conditionally display different components with ion-segment?
Thanks in advance!
<IonToolbar>
<IonSegment value ="register" onIonChange={(e) => handleSegmentChange(e)}>
<IonSegmentButton value="register">
<IonLabel>Register</IonLabel>
</IonSegmentButton>
<IonSegmentButton value="login">
<IonLabel>Login</IonLabel>
</IonSegmentButton>
</IonSegment>
</IonToolbar>
</IonHeader>
<IonContent>
<IonCard>
Register card that appears when I click the "Register" segment
</IonCard>
<IonCard>
Login card that appears when I click the "Login" segment
</IonCard>
</IonContent>
Here's what I'm trying to accomplish.
Find out the solution below. For me is working properly.
import {
IonCard,
IonContent,
IonHeader,
IonLabel,
IonPage,
IonSegment,
IonSegmentButton,
IonToolbar,
} from "#ionic/react";
import React, { useState } from "react";
const Segments = () => {
const [registerActive, setRegisterActive] = useState<boolean>(true);
const [loginActive, setLoginActive] = useState<boolean>(false);
return (
<React.Fragment>
<IonPage className="ion-page" id="main-content">
<IonHeader>
<IonToolbar>
<IonSegment value={registerActive ? "register" : "login"}>
<IonSegmentButton
value="register"
onClick={() => {
setLoginActive(false);
setRegisterActive(true);
}}
>
<IonLabel>Register</IonLabel>
</IonSegmentButton>
<IonSegmentButton
value="login"
onClick={() => {
setRegisterActive(false);
setLoginActive(true);
}}
>
<IonLabel>Login</IonLabel>
</IonSegmentButton>
</IonSegment>
</IonToolbar>
</IonHeader>
<IonContent className="ion-padding">
{registerActive ? (
<IonCard>
Register card that appears when I click the "Register" segment
</IonCard>
) : (
<IonCard>
Login card that appears when I click the "Login" segment
</IonCard>
)}
</IonContent>
</IonPage>
</React.Fragment>
);
};
export default Segments;
Hope this helps you!

Formik Form validation in react

I have implemented form validation with formik and react. I am using material-UI.
<Formik
initialValues={{ name: '' }}
onSubmit={values => {
console.log('submitting', values);
}}
validate={values => {
alert();
let errors = {};
if (!values.name) {
errors.name = 'Name is required';
}
return errors;
}}>
{({
handleSubmit,
handleChange,
values,
errors
}) => (
<form onSubmit={handleSubmit}>
<div>
<input name="name"
onChange={handleChange}
name="name"
value={values.name}
type="text"
placeholder="Name">
</input>
{errors.name &&
<span style={{ color: "red", fontWeight: "bold" }}>
{errors.name}
</span>
}
</div>
<div>
<button>Submit</button>
</div>
</form>
)}
</Formik>
Above code is working fine for normal input tags but it is not working for Select and TextField material widgets.
Is there a compatibility issue with material UI ?
Please help.
As Chris B. commented, the solution is to wrap each desired element inside a React component that has what Formik requires. In the case of Material-UI, Gerhat on GitHub has created some of those components.
You can use those by downloading the source from the github link above. There is also a usage example there, showing how to use Gerhat's "wrapper" for a Material TextField and a Select.
In Gerhat's usage example, TextField is a component in that github repo; it isn't the Material UI TextField directly; it is a Formik-compatible "wrapper" around the Material TextField widget.
By looking at gerhat's source code, you can learn how to do the same for other Material widgets you need.
HOWEVER, gerhat's implementation may not be the easiest for a beginner to understand. Those wrappers are easy to use, but it may not be obvious from that code how to write your own wrappers for other widgets or components.
See my answer here for a discussion of Formik's <Field> and useField. Those are easier ways to "wrap" existing React components. (Not specifically Material-UI widgets, but AFAIK, you can wrap those like any other React component.)
If you do want to understand gerhat's approach, here are some comments about the code you'll see at github.
This is the source to TextField.jsx in that repo.
The "heart" of TextField.jsx, is its wrapping around Material's TextField. The generated virtual-DOM element (representing a Material TextField) is seen in these lines:
return (
<TextField
label={label}
error={hasError}
helperText={hasError ? errorText : ''}
{...field}
{...other}
/>
)
See the source link above, for the details of how this is made compatible with Formik. IMHO, a fairly advanced understanding of both React and Formik is required, to understand what is being done there. This is why I mentioned Field and useField as the place to start, for writing your own "Formik-compatible wrappers".
One detail I'll mention. The implementation relies on a file index.js in the same folder as TextField.jsx, to map the default of TextField.jsx, which is FTextField, to the name TextField, which is how you refer to it in the "usage" code at the start of this answer. SO Q&A about index.js file of a React component.
index.js contents:
export { default as TextField } from './TextField'
The other two files in the TextField source folder are ".d.ts" files. See this Q&A to understand those. You don't need them unless you are using TypeScript.

Redux DevTools could not render

I am using redux-devtools with redux-devtools-dock-monitor and redux-devtools-log-monitor.
I followed documentation. However, in the console I receive this error:
index.js:1452 Redux DevTools could not render.
You must pass the Redux store to <DevTools> either as a "store" prop
or by wrapping it in a <Provider store={store}>.
Here is my Root component:
const Root = () => {
return (
<Provider store={store}>
<div>
<h1>Hello !!!</h1>
<DevTools/>
</div>
</Provider>
);
};
export default Root;
Additionally, I am getting this warning too:
redux-devtools#3.4.2" has incorrect peer dependency "react-redux#^4.0.0 || ^5.0.0".
I have used redux-devtools-log-monitor and redux-devtools-dock-monitor as monitors
I've tried the suggestion and now it gives another error (I'm using the DockMonitor). Ie this is my setup.
<DockMonitor toggleVisibilityKey='ctrl-h'
changePositionKey='ctrl-q'
changeMonitorKey='ctrl-m' >
<LogMonitor />
</DockMonitor>
<Provider store={store}>
<App />
<DevTools store={store} />
</Provider>
Produces the following error:
Uncaught Error: Passing redux store in props has been removed and does not do anything. To use a custom Redux store for specific components, create a custom React context with React.createContext(), and pass the context object to React-Redux's Provider and specific components like: . You may also pass a {context : MyContext} option to connect
In react-redux#6, the store is not passed via legacy React context and you should specify it explecitely via props like so:
<DevTools store={store}/>
Update 1: It was working for me because I had react-redux#6 in main project, but react-redux#5 for redux-devtools dependency. So if someone needs a quick workaround (you shouldn't include DevTools component in production anyway) till it will be supported, just do: cd ./node_modules/redux-devtools && npm i react-redux#5.
Update 2: redux-devtools#3.5.0 was just published, which adds support for react-redux#6.

Reactjs issues during Initial Animation

Still i am getting error -
Failed prop type: transitionLeaveTimeout wasn't supplied to
ReactCSSTransitionGroup: this can cause unreliable animations and
won't be supported in a future version of React
My render looks -
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
render(){
const {...others} = this.props;
return(<div id="navigation">
<img id="openNav" onClick={this.handleClick} src={this.state.source}/>
{this.state.clicked ?
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500}>
<Navigation {...others} />
</ReactCSSTransitionGroup>: false}
</div>
)
}
"react": "^15.2.1",
i dont know where is the problem...
The warning you're getting is due to a change documented in the React v0.14 changelog:
Add-Ons: To improve reliability, CSSTransitionGroup will no longer listen to transition events. Instead, you should specify transition durations manually using props such as transitionEnterTimeout={500}.
The code examples have been updated in the documentation but the props are not really documented.
You'll need to add these two props (transitionEnterTimeout and transitionLeaveTimeout) yourself.
<ReactCSSTransitionGroup
transitionName="example"
transitionAppear={true}
transitionAppearTimeout={500}
transitionEnterTimeout={500}
transitionLeaveTimeout={500}>
You can also disable animating enter and leave events if you want by using the transitionEnter={false} or transitionLeave={false} props to ReactCSSTransitionGroup.
You have to add transitionLeaveTimeout to your ReactCSSTransitionGroup component, so your render looks with 500ms leave timeout like this:
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
render(){
const {...others} = this.props;
return(<div id="navigation">
<img id="openNav" onClick={this.handleClick} src={this.state.source}/>
{this.state.clicked ?
<ReactCSSTransitionGroup transitionName="example" transitionAppear={true} transitionAppearTimeout={500} transitionLeaveTimeout={500}>
<Navigation {...others} />
</ReactCSSTransitionGroup>: false}
</div>
)
}

Resources