Closed JinbeiStudio closed 1 year ago
I am not seeing an issue when I try to reproduce, are you using the BreakpointProvider or no? And would you be able to provide a larger set of code to reproduce?
I am not seeing an issue when I try to reproduce, are you using the BreakpointProvider or no? And would you be able to provide a larger set of code to reproduce?
Hey :)
I am not using the BreakpointProvider. It is only necessary when using custom breakpoints right ?
I have the issue both on my local dev environement, and on my prod environment. A simple refresh in chrome cause to have the lower breakpoints styles.
Techno wise, I have a monorepo with next js for the web and expo for mobile. Based on the solito monorepo : https://github.com/nandorojo/solito/tree/master/example-monorepos/blank
Here is an example of a page :
import { View, ScrollView } from 'react-native';
import { TextInput, Headline, HelperText, Surface, Button, Snackbar } from 'react-native-paper';
import React from 'react';
import { useForm, Controller } from 'react-hook-form';
import { useUser } from 'app/functions/hooks/useUser';
import { useState, useEffect } from 'react';
import { useRouter } from 'solito/router';
import { CreateResponsiveStyle, DEVICE_SIZES, maxSize } from 'rn-responsive-styles';
export default function LoginForm() {
const { login, loggedIn } = useUser();
const [visibleSnackBar, setVisibleSnackBar] = useState(false);
const { push } = useRouter();
const styles = useStyles();
const {
control,
handleSubmit,
formState: { isSubmitting, errors },
setError,
} = useForm({
defaultValues: {
email: '',
password: '',
api: '',
},
});
const onSubmit = ({ email, password }: SubmitTypes) => {
return login(email, password).catch((error) => {
setError('api', {
message: error?.response?.data?.message,
});
});
};
const onDismissSnackBar = () => setVisibleSnackBar(false);
useEffect(() => {
if (loggedIn) {
setVisibleSnackBar(true);
setTimeout(() => {
push('/');
}, 2000);
}
}, [loggedIn, push]);
return (
<View style={styles.pageContainer}>
<View style={styles.container}>
<ScrollView
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.scrollView}>
<Surface style={styles.surface}>
<Headline style={styles.title}>Se connecter</Headline>
<Controller
name="email"
control={control}
rules={{
required: { value: true, message: 'Ce champs est requis.' },
}}
render={({ field: { onChange, onBlur, value } }) => (
<TextInput
left={<TextInput.Icon name="email" />}
textContentType="emailAddress"
mode={'outlined'}
label="Email"
autoCapitalize="none"
onBlur={onBlur}
onChangeText={onChange}
value={value}
style={styles.input}
error={errors.email ? true : false}
/>
)}
/>
{errors.email && (
<HelperText type="error">{errors.email.message}</HelperText>
)}
<Controller
name="password"
control={control}
rules={{
required: { value: true, message: 'Ce champs est requis.' },
}}
render={({ field: { onChange, onBlur, value } }) => (
<TextInput
left={<TextInput.Icon name="onepassword" />}
secureTextEntry
textContentType="password"
mode={'outlined'}
label="Mot de passe"
onBlur={onBlur}
onChangeText={onChange}
value={value}
style={styles.input}
error={errors.password ? true : false}
/>
)}
/>
{errors.password && (
<HelperText type="error">{errors.password.message}</HelperText>
)}
<Button
style={styles.loginButton}
icon="account"
mode="contained"
loading={isSubmitting ? true : false}
onPress={handleSubmit(onSubmit)}>
Connexion
</Button>
{errors.api && (
<HelperText type="error">
Une erreur s'est produite lors de la connexion.
</HelperText>
)}
</Surface>
<Surface style={styles.surface}>
<Headline style={styles.title}>Pas encore inscrit ?</Headline>
<Button
icon="account-plus"
mode="contained"
onPress={() => push('/register')}>
Je m'inscris
</Button>
</Surface>
</ScrollView>
</View>
<Snackbar
wrapperStyle={styles.snackbarWrapper}
visible={visibleSnackBar}
onDismiss={onDismissSnackBar}>
Vous êtes désormais inscrit !
</Snackbar>
</View>
);
}
const useStyles = CreateResponsiveStyle(
{
pageContainer: {
flex: 1,
},
surface: {
padding: 50,
minHeight: 400,
minWidth: 400,
margin: 16,
justifyContent: 'center',
},
container: {
alignItems: 'center',
justifyContent: 'center',
flex: 1,
},
title: {
textAlign: 'center',
padding: 16,
},
input: {
marginTop: 16,
minWidth: 300,
},
loginButton: {
marginTop: 24,
},
scrollView: {
alignItems: 'center',
flexDirection: 'row',
minHeight: '100%',
},
snackbarWrapper: {
top: 0,
},
},
{
[maxSize(DEVICE_SIZES.SMALL_DEVICE)]: {
input: {
minWidth: 300,
},
surface: {
padding: 20,
width: 340,
height: 300,
minWidth: undefined,
minHeight: 400,
},
scrollView: {
flexDirection: 'column',
},
},
}
);
type SubmitTypes = {
email: string;
password: string;
};
I tried adding the breakpoint provider but the issue remain the same.
@JinbeiStudio Sorry I forgot to reply, I tried reproducing this and still cannot get the behavior you are saying. Is there any way you could provide a full reproducible example? I have an app I am working on off of the Solito example and I tried pasting in that style you said and it behaves correctly, I tried refreshing and changing device sizes and couldn't reproduce
@khevamann Here is a simple example to reproduce.
If I access the page with the navigation, surface display in rows, if I refresh the browser surface display in column. As if the size of the device detected was not the good one.
Thank you.
import { View } from 'react-native';
import React from 'react';
import { Surface, Text } from 'react-native-paper';
import { CreateResponsiveStyle, DEVICE_SIZES, maxSize } from 'rn-responsive-styles';
export default function Test() {
const styles = useStyles();
return (
<View style={styles.view}>
<Surface style={styles.surface}>
<Text>Test1</Text>
</Surface>
<Surface style={styles.surface}>
<Text>Test2</Text>
</Surface>
</View>
);
}
const useStyles = CreateResponsiveStyle(
{
surface: {
padding: 50,
minHeight: 400,
minWidth: 400,
margin: 16,
justifyContent: 'center',
},
view: {
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
minHeight: '100%',
},
},
{
[maxSize(DEVICE_SIZES.SMALL_DEVICE)]: {
view: {
flexDirection: 'column',
},
},
}
);
@JinbeiStudio I also tried with the surfaces and this example does not break. https://snack.expo.dev/@khevamann/rn-responsive-styles---issue-17-repro if you can provide an example that is broken I am happy to look at it, but I am unable to reproduce with the snippet you sent me or in my own solito app.
@JinbeiStudio I also tried with the surfaces and this example does not break. https://snack.expo.dev/@khevamann/rn-responsive-styles---issue-17-repro if you can provide an example that is broken I am happy to look at it, but I am unable to reproduce with the snippet you sent me or in my own solito app.
I managed to find where the issue lies. I am using nextJS and there is a mismatch between the style generated server side and client side.
It appears to be because the window dimensions can't be retrieved by nextJS on the server side :
Dimensions.get('window'))
Here is a github discussion regarding this subject. nandorojo created the Dripsy library that implements a responsive style approach as well. https://github.com/vercel/next.js/discussions/14469
I managed to find a solution by checking if window var is set or not, with a default width if not. This deal with framework having server side rendering like NextJs.
export default function useDeviceSize() {
const breakpoints = useBreakpoints();
const [isServer, setIsServer] = useState(true);
useEffect(() => {
if (typeof window !== 'undefined') {
setIsServer(false);
}
}, [isServer]);
const [dims, setDims] = useState(() =>
!isServer ? Dimensions.get('window') : { width: 1200 }
);
Hello! I have same problem. When page loads on desktop I see responsive styles [maxSize(DEVICE_SIZES.SM)]
but when I resize window to mobile and return back the styles becomes fine. It works in wrong way after page loads on Desktop. I use RNW with Next.js. P.S. Thanks for great job!
I've done preview https://stackblitz.com/edit/next-js-rn-responsive-styles?file=pages%2Findex.js
You can press "Open in New Tab" and try it. On load on wide screen we have color: red
but we need to have color: blue
.
But after resize from desktop to mobile our color becomes fine.
@arturmoroz Thank you for this! I will take a look at it this weekend and get a fix out!
@khevamann I have the same problem, help me plz
I will have a PR ready for this by tonight. I was trying to find a good solution to this for a bit, but it looks like the recommended approach is to delay rendering until it has reached the client. So with Next and SSR enabled, I am adding a new provider that can be used to delay rendering until it is off the server.
Hello,
When reloading my page on the web, the page adopt the style specified in maxSize, instead of the default one.
On refresh it goes from row to column. No issue if I access the page with a link.