How to allow the props of every component to be defined in one central place in react native? - react-native

the question is clear. I think it can be done with react native elements. But how? I am very new to react native.
I read the documentation in here. It has a code like this:
import { ThemeProvider, Button } from 'react-native-elements';
const theme = {
Button: {
raised: true,
},
};
// Your App
const App = () => {
return (
<ThemeProvider theme={theme}>
<Button title="My Button" />
<Button title="My 2nd Button" />
</ThemeProvider>
);
};
What if this part of the code:
const theme = {
Button: {
raised: true,
},
};
was coded in another file. How will I make the buttons raised?

You have 2 ways to aboard your problem.
First, if you want to use the same style for your react-native-elements components across certain files and they are all the children of the same parent file, you use this bit of code :
<ThemeProvider theme={theme}>
<Button title="My Button" />
<Button title="My 2nd Button"/> // ... plus any other component that contains your react native elements components
</ThemeProvider>
for this case if you want to put your config variable in another file , you can do it like this :
create a new file that contains your config variable let say for example a new file called config.js
// config.js file
export default {
Button:{
raised:true
}
// ... other RN-elements props
}
// or this
const theme = {
Button: {
raised: true,
},
}
export {theme}
then import it in your workspace like so :
// the file were you are using your themeProvider
import theme from "path_to_your_config.js_file"
// or respectively
import {theme} from "path_to_your_config.js_file"
// then use the variable theme as you like
the second way is that you create your own custom component and you style it however you want and you use it in your app.

Related

React Native app with react-hook-form not working (View config getter callback form component 'input' must be a function (received 'undefined')

I'm creating a mobile app with React Native and I need to use a form. I want to use react-hook-form, but I can't get it to work, even in a newly created project. I did the following:
Created new React Native projects: it runs as it should
npm install react-hook-form
copy-paste following code to App.js:
import React from "react";
import { useForm } from "react-hook-form";
export default function App() {
const { register, handleSubmit, watch, formState: { errors } } = useForm();
const onSubmit = data => console.log(data);
console.log(watch("example")); // watch input value by passing the name of it
return (
/* "handleSubmit" will validate your inputs before invoking "onSubmit" */
<form onSubmit={handleSubmit(onSubmit)}>
{/* register your input into the hook by invoking the "register" function */}
<input defaultValue="test" {...register("example")} />
{/* include validation with required or other standard HTML validation rules */}
<input {...register("exampleRequired", { required: true })} />
{/* errors will return when field validation fails */}
{errors.exampleRequired && <span>This field is required</span>}
<input type="submit" />
</form>
);
}
It gives following error: screenshot of emulator
I have no idea what's the problem. Is there something wrong with the installation of react-hook-form as it doesn't recognize the input field?
Thanks!

use React Hook in multi files?

Senario : I have a dialog, and i use a react-hook to make it disappear ,like const[show,setShow]= useState(false) , this dialog file is a seperate file with main screen file, which contain button to show this dialog
Problem : I don't know how to show this dialog in main screen, for example, my dialog file called Mydialog.js have componet Mydialog, so i tried to put that hook show in props , Mydialog(show), but look like it not work that way, i still can't show the dialog
Question. How can i use react-hook for multi file, like i have hook in dialog file, present the dialog status ( show or not) then i can use it in mainScreen file to set show to true, then i can use that show and set to false when click button in dialog
If I understood it right you're trying to bring up a dialog when you interact with something on the main page and then close it by clicking on the X within the dialog. Would something like this work?
Main.js:
import "./styles.css";
import { useState } from "react";
import MyDialog from "./MyDialog";
export default function App() {
const [showDialog, setShowDialog] = useState(false);
const handleDialog = () => {
setShowDialog(!showDialog);
};
return (
<>
<button onClick={handleDialog}>Show Dialog</button>
Show Dialog: {showDialog?.toString()}
{showDialog && <MyDialog handleDialog={handleDialog} />}
</>
);
}
MyDialog.js:
import "./styles.css";
export default function MyDialog({ handleDialog }) {
return (
<>
<div className="popup">
<div className="popup_open">
<h1>Dialog Content</h1>
<button onClick={handleDialog}>X</button>
</div>
</div>
</>
);
}
Sandbox link if you want to test: https://codesandbox.io/s/admiring-feather-sy1gf
You can use Context to maintain state between multiple components.
const DialogContext = createContext();
const DialogProvider = ({ children }) => {
const [isDialogVisible, setDialogVisible] = useState(false);
const value = {
isDialogVisible,
setDialogVisible,
}
return <DialogContext.Provider value={value}>{children}</DialogContext.Provider>
}
const useDialog = () => {
const context = useContext(DialogContext);
return context;
}
Render the DialogProvider in one of the top-level components, for example in App.js.
// App.js
return (
<DialogProvider>
// ...
</DialogProvider>
)
Then inside of your components you can use your hook and trigger the visibility of the dialog.
MyComponentA:
const { isDialogVisible, setDialogVisible } = useDialog();
const toggleDialogVisibility = () => {
setDialogVisible(!isDialogVisible);
}
return (
<Button title="Toggle" onPress={toggleDialogVisibility} />
)
MyComponentB:
const { isDialogVisible } = useDialog();
if(isDialogVisible) {
return <Text>My Dialog</Text>
}
return null;
A very simple example of usage, here's a Snack for the above.

Unknown named Module, using component will receive props to update an image

Hi I am running into the error "Unknown named Module" when trying to dynamically update image using componentWillReceiveProps. Essentially I have a topics component which has a list of topics, when a topic is clicked it gives props to another component (thumbnails) and the images related to that topic are populated.
Here is some code for the thumbnails component:
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image, Button } from 'react-native';
import Player from './player.js';
import styles from '../stylesheet.js';
let baseurl = '../assets/thumbnails/';
let extension = '.jpeg';
export default class Thumbnails extends Component {
constructor(props){
super(props);
this.state = {
current: [
require('../assets/thumbnails/narcolepsy-1.jpeg'),
require('../assets/thumbnails/narcolepsy-2.jpeg'),
require('../assets/thumbnails/narcolepsy-3.jpeg')
]
}
}
componentWillReceiveProps(nextProps) {
setTimeout(()=>{
let topic = nextProps.current.toLowerCase();
let current = [];
for(let i = 1; i <= 3;i++){
current.push(require(baseurl + topic + '-' + i + extension));
}
this.setState({current,})
},1000)
}
render() {
const thumbnails = this.state.current.map((path,i) => {
return(<Image
source={path}
style={styles["thumbnail"+(i+1)]}
key={"thumbnail"+i} />);
})
return(
<View style={{flexDirection:'row'}}>
{thumbnails}
</View>
)
}
}
I've found a similar question (React-native image - unknown named module '../img/2.jpeg') that says to use source={uri: 'file.extension'};
and to keep image assets in the folder android/app/src/main/res/drawable
However I do not have an android folder, as I am using CRNA and Expo.io. Here is my project structure, please tell me what to do in this context:
App.js app.json my-app-key.keystore stylesheet.js
App.test.js assets node_modules yarn.lock
README.md components package.json
Using dynamic require calls is not supported by the React Native packager. This is outlined in the docs: React Native - Images
In order for this to work, the image name in require has to be known statically.
// GOOD
<Image source={require('./my-icon.png')} />
// BAD
var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive';
<Image source={require('./' + icon + '.png')} />
// GOOD
var icon = this.props.active ? require('./my-icon-active.png') : require('./my-icon-inactive.png');
<Image source={icon} />
I would suggest creating a static data structure to hold your images, such as an object like:
const images = {
narcolepsy: [
require('../assets/thumbnails/narcolepsy-1.jpeg'),
require('../assets/thumbnails/narcolepsy-2.jpeg'),
require('../assets/thumbnails/narcolepsy-3.jpeg')
],
apnea: [
require('../assets/thumbnails/apnea-1.jpeg'),
require('../assets/thumbnails/apnea-2.jpeg'),
require('../assets/thumbnails/apnea-3.jpeg')
]
};
This way, the packager can load your references up when the bundle is created.

How to create and connect a custom component theme for Native Base

I'm using Native Base 2.0+, the themes are ejected and using StyleProvider I am able to tweak and customize any Native Base component according to my theme, no problem.
Following the docs, it's stated that to add themes to a custom component we should define a namespace for said component and merge it with the instantiated styling as well. Code example below:
import React, { Component } from 'react'
import { Header, Left, Body, Right, Button, Title, Text, connectStyle } from 'native-base'
import Colors from '../Themes/Colors'
import ApplicationStyles from '../Themes/ApplicationStyles'
class NBHeader extends Component {
render () {
const styles = this.props.style
return (
<Header style={styles.header}>
<Left>
<Button transparent>
<Text style={styles.headerBackButton}>
{'< Back'}
</Text>
</Button>
</Left>
<Body>
<Title>Login</Title>
</Body>
<Right />
</Header>
)
}
}
export default connectStyle('CustomComponents.Header', ApplicationStyles)(NBHeader)
In this case, namespace for the component is 'CustomComponents.Header'. Then, we use StyleProvider to connect the Theme:
import React, { Component } from 'react';
import { StyleProvider } from 'native-base';
class CustomComponent extends Component {
render() {
return (
// connect styles to props.style defined by the theme
const styles = this.props.style;
<StyleProvider style={customTheme}>
Your Custom Components
</StyleProvider>
);
}
}
// Define your own Custom theme
const customTheme = {
'yourTheme.CustomComponent': {
// overrides CustomComponent style...
}
};
Since I've ejected the theme, I entered the new namespace for the Custom Component in NB's Theme file, so it should already be added and cascaded using StyleProvider.
So for instance, if I want the header to be 'red' and have a padding of '10' due to theming rules, I add those as default props of 'CustomComponents.Header' and forget about it, it will always be applied to the component as long as the StyleProvider is cascading themes.
The problem is I cannot get this defined Custom Component's default theme to be applied. I don't know if it's a problem with my code or how Native Base works. Any help would be appreciated and I can provide further code if needed.

Implement Hero animation like shoutem About extension

I try to implement the hero animation like in the shoutem About extension. Basically, I add animationName to NavigationBar and the Image like in the extension. I also had to add ScrollDriver because it would error-ed otherwise. But it seems the NavigationBar does not pass the driver down to its child components, so I still got this error. Is it possible to implement the hero animation like what was demonstrated here? https://medium.com/shoutem/declare-peace-with-react-native-animations-e947332fa9b1
Thanks,
import { ScrollDriver } from '#shoutem/animation';
getNavBarProps() {
const driver = new ScrollDriver();
return {
hasHistory: true,
driver: driver,
title: 'Title',
navigateBack: () => this.props.navigation.dispatch(NavigationActions.back()),
styleName: 'fade clear',
animationName: 'solidify',
};
}
render () {
const driver = new ScrollDriver();
return (
<Screen styleName=" paper">
<View style={{height:68}}>
<NavigationBar {...this.getNavBarProps()} />
</View>
<ScrollView style={styles.container}>
<Image
styleName="large"
source={require('../Images/spa2.jpg') }
defaultSource={require('../Images/image-fallback.png')}
driver={driver}
animationName="hero"
/>
...
I'm the author of the article, from you question, I'm not sure are you trying to create an extension on shoutem or you just want to recreate animation in any other React Native app.
If you are creating an extension or CardStack from #shoutem/ui/navigation, you don't event need to care for ScrollDriver. It would be pushed throught the context to the ScrollView (imported from #shoutem/ui) and NavigationBar (imported from #shoutem/ui/navigation).
If you are creating your own React Native project to be able to do it like in article I suggest the following. At the root component of your app:
import ScrollView from '#shoutem/ui';
class App extends Component {
...
render() {
return (
<ScrollView.DriverProvider>
<App />
</ScrollView.DriverProvider>
);
}
}
Then you don't have to take care of initialization of ScrollDriver on each screen, if you use our components and a ScrollView it will push the driver where it needs to be. :) So your screen at the end would look like this:
import {
ScrollView,
NavigationBar,
Image
} from '#shoutem/ui';
class MyScreen extends Class {
render() {
return (
<Screen>
<NavigationBar animationName="solidify" />
<ScrollView>
<Image animationName="hero" />
</ScrollView>
</Screen>
);
}
}
The whole working example is here https://github.com/shoutem/ui/tree/develop/examples/RestaurantsApp/app