React Native Dynamic Component name error - react-native

I'm developing my first app with React Native and i'm stuck in a problem with dynamic component name.
I call a class named IconAccounts with two props: icon and bgColor. The props icon represent the component (a react native SVG component) that need to render inside IconAccount.
Everything should work but i have an error:
Invariant Violation: View config not found for name iconName
IconAccount :
import iconName from "../path/to/iconName"
someMethods(){}
render(){
const TagName = this.props.icon
return (
<View style={{backgroundColor: '#'+this.props.bgColor}}>
<TagName/>
</View>
)
}
Call of IconAccount :
<IconAccounts icon="iconName" bgColor="#ffffff"/>
icon code example (generate with svg-to-react-native-cli)
export default function iconName(props) {
return (
<Svg>
//SvgThings
</Svg>
);
}

Related

Is there a way to use tailwind-rn for styling React Native Class Components?

i installed tailwind-rn for my react native project
i did the configuration and used this syntax provided in the console after installation
import {useTailwind} from 'tailwind-rn';
const MyComponent = () => {
const tailwind = useTailwind();
return <Text style={tailwind('text-blue-600')}>Hello world</Text>;
};
but for me i have a class component so i did this
render() {
const tailwind = useTailwind();
return (
<View style={tailwind("style classes...")}>
...
<View/>
);
}
and i got this error
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
i searched how to use tailwind-rn for a class component and i didn't find something usefull.

How can we create a react-native component which can be displayed with .show() method

I am looking for pointers where I can start from.
I want to create a react native feedback form which can be displayed with .show method.
for eg:
export class FeedbackComponent extends React.component{
show() {
// define this method in a way so that can be called from outside as FeedbackComponent.show()
// which eventually create a new screen with below rendered View
}
render (){
return <View>Feedback Form</View>
}
}
I should be able to use this Component in any other component as
import FeedbackComponent from './FeedbackComponent'
new FeedbackComponent.show()
I would always start with considering the application state. UI in React is updated whenever the State of our components changes.
In your case I would have to think of the parent context in which your feedback form will need to be displayed. In its simplest form, this context will likely be a parent screen-component within which your FeedbackForm component is either shown or hidden.
I've made a Snack of a simple implementation you can find it here: https://snack.expo.io/#stephos_/show-feedback-form
In my case, the App component is the parent screen-component within which we need to render or not render a FeedbackForm Component.
So I would start with adding the relevant state property to the App (parent screen) component like so:
state = {
feedbackFormVisible : false
}
I would then define a method within the same parent class in order to toggle the state when we need to like so:
handleFeedbackFormVisibility = () => this.setState(prevState => ({feedbackFormVisible:!prevState.feedbackFormVisible}))
This handler takes in the previous state in our parent component and toggles the value of the feedbackFormVisible property (i.e. from false to true).
In my case, I call this handler every time we press a Button component like so:
<Button title="Give Feedback" onPress={this.handleFeedbackFormVisibility}/>
You could however trigger the same handler and update the state of the parent component in any other way (i.e. after a timer expires or after a specific scroll point is passed).
The App Component's render method will then decide if the FeedbackForm component should be displayed based on the value of the feedbackFormVisible in our App Component's state. We achieve this by wrapping our FeedbackForm component within an Elvis Conditional within the render method which will return the the appropriate UI (i.e. either with a visible feedback form or not):
{ this.state.feedbackFormVisible ? () : null}
Below the full App component code:
import * as React from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import FeedbackForm from './components/FeedbackForm';
export default class App extends React.Component {
state = {
feedbackFormVisible : false
}
handleFeedbackFormVisibility = () => this.setState(prevState => ({feedbackFormVisible:!prevState.feedbackFormVisible}))
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
This is the App Parent Component
</Text>
{
this.state.feedbackFormVisible ?
(<FeedbackForm />)
: null
}
<Button title="Give Feedback" onPress={this.handleFeedbackFormVisibility}/>
</View>
);
}
}
And below the Feedback Component code (Notice that the shown/hidden logic is actually handled in the parent component not in here):
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class FeedbackForm extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
This is the feedback form!
</Text>
</View>
);
}
}

Is it possible to render two headers on one screen using React Navigation?

I'm writing an iPad / Android Tablet app with React Native and I'm using React Navigation for the navigation.
The mock up I received has a screen which is split in half (in landscape mode) with two different headers. Is is possible to achieve this with react navigation?
What I've tried is setting header: null in the navigation options for the screen, and then rendering two components on that split screen, each of the components has React Navigation's Header component as the first child. This somehow does not work (the header does not get rendered).
Like you can see in the source of Header it does not render if the header option is null:
_renderHeader(props) {
const { options } = props.scene.descriptor;
if (options.header === null) {
return null;
}
...
}
So using the Header component manually will not work.
You could just create your own Header components with a title and a "back" touchable. If a designer gave you a mock up I assume the Header must be styled very differently from original Header component anyway :)
Your component could look like this:
export default class MyCustomHeader extends Component {
handlePress = () => {
const { navigation } = this.props;
navigation.goBack(); // or .navigate() to whatever you want
};
render() {
return (
<View>
<TouchableHighlight onPress={this.handlePress}>
<some-icon>
</TouchableHighlight>
<Text>My title</Text>
</View>
);
}
}
With proper styling of course :)

Reusable Button with image tag (React Native)

I want to turn this section of code into a reusable component so I don't have to write the same thing out 5 times.
<TouchableOpacity onPress={console.log('pressed')}>
<Image
source={require('../img/button_australia.png')}
/>
</TouchableOpacity>
The new component I made to mirror this is as follows:
import React from 'react';
import { Image, TouchableOpacity } from 'react-native';
const ImgButton = ({ onPress, img }) => {
return (
<TouchableOpacity onPress={onPress}>
<Image
source={require(img)}
/>
</TouchableOpacity>
);
};
export { ImgButton };
After importing this component ImgButton I call it with this block of code:
<ImgButton
onPress={console.log("pressed")}
img={'../img/button_australia.png'}
/>
I get the error: "Requiring unknown module '../img/button_australia.png'"
I assume I've gone wrong when passing the string down as a prop but from the examples I've looked I don't see what's wrong with what I've done. Thanks :)
As discussed in this react-native issue, it's not possible to require assets or javascript modules with dynamically generated names, e.g. variables.
This is because the React Native packager uses require (and import) statements to generate the module and asset bundles at compile-time, so the value of the variable is not known.
The simplest way is to just pass the image source to the component directly:
<ImgButton
onPress={console.log("pressed")}
img={require('../img/button_australia.png')}
/>

expected a component class, got [object Object]

I get an error with this code. However, changing to react-native's removes the error. Can you use div with react-native? If not, why is this error so obscure...?
var React = require('react');
var ReactNative = require('react-native');
var {
StyleSheet,
Text,
View,
} = ReactNative;
let Auto = React.createClass({
getInitialState: function() {
return { value: 'Ma' }
},
render: function() {
return (
<div className="fuck-react">
Blah blah blah
</div>
)
}
});
No you cannot use div tag in react-native. Since, react-native is based on JSX syntax which are automatically dispatched to native components by abstract Dom parser. you can get your answer here:https://facebook.github.io/react-native/docs/tutorial.html
Also, react-native is upadated to new version that is 0.29 , you probably should ignore old ECMA script and use new ECMA script for javascript syntax. Since, react-native uses reactjs for its javascript so better learn from here: http://reactjs.net/guides/es6.html
Instead of DIV use View.
<View style={{flex: 1}}>
<Text>Blah blah blah</Text>
</View>
You can not use in react native. Use native component instead.
<View>
<Text>text text text</Text>
</View>
Do not forget to import before with:
import {
Text,
View
} from 'react-native';
You may be using ReactJS component in a React Native App. I accidentally installed a component with <div> tags in React Native project.