I have a styled class component below, it define a TextInput and with Icon and placeholder two props.
import React, { Component } from "react";
import { View, Text, TextInput } from "react-native";
import styled from "styled-components/native";
const StyledView = styled.View`
...
`;
const StyledIconView = styled.View`
...
`;
const StyledTextInput = styled.TextInput`
...
`;
class LoginTextInput extends React.Component {
constructor(props) {
super(props);
this.state = { text: this.props.text };
}
render() {
const { Icon } = this.props; // it seems have a problem here
return (
<StyledView>
<StyledIconView>
<Icon /> // and here
</StyledIconView>
<StyledTextInput
placeholder={this.state.text}
onChangeText={searchString => {
this.setState({ searchString });
}}
/>
</StyledView>
);
}
}
export default LoginTextInput;
And then I can use this component to customize my own case.
import React from "react";
import { View, Text, StyleSheet, TextInput } from "react-native";
import LoginTextInput from "./LoginTextInput";
import Icon from "react-native-vector-icons/FontAwesome";
import SimpleIcon from "react-native-vector-icons/SimpleLineIcons";
const UserIcon = () => <Icon name="user-o" size={20} color="#757575" />;
class Login extends React.Component {
constructor(props) {
super(props);
this.state = { text: "Useless Placeholder" };
}
render() {
return (
<View>
/* <LoginTextInput text="input use name" Icon={UserIcon} /> */
<LoginTextInput text="input use name" Icon={<UserIcon />} />
</View>
);
}
}
export default Login;
But this code can not be compiled and report a "expect a string or a class/function, but get: undefined" error.
I tag the error above, it seems the Icon props can not be defined in this code.
SOLUTION
Because I use the component UserIcon, so it should be let it changed to <UserIcon / >.
Related
I've got an error when creating new component in React Native
I don't know what causes this error because I already declare the View component
"react-native": "0.65.1"
the code in the component
import React from 'react';
import { Text, View } from 'react-native';
import Styles from './Styles';
import CommonUtils from '../../components/base/CommonUtils';
import Constant from '../../constants/Constant';
class FrequentlyAskedQuestion extends React.Component {
navigationOptions = (route, navigation) => {
return CommonUtils.getBackNavigationHeader(route, navigation, Constant.HEADER_TITLE.FAQ, 1, false, true);
};
constructor(props) {
super(props);
this.state = {
}
}
componentDidMount() {
this.props.navigation.setOptions(this.navigationOptions(this.props.route, this.props.navigation));
}
render() {
return (
<View>
<Text>
asda
</Text>
</View>
)
}
}
export default FrequentlyAskedQuestion;
Tried exactly with your code,couldnt replicate the error
https://snack.expo.dev/#gaurav1995/gnarly-marshmallows
import React from 'react';
import { Text, View } from 'react-native';
class FrequentlyAskedQuestion extends React.Component {
navigationOptions = (route, navigation) => {
return null
};
constructor(props) {
super(props);
this.state = {
}
}
componentDidMount() {
// this.props.navigation.setOptions(this.navigationOptions(this.props.route, this.props.navigation));
}
render() {
return (
<View>
<Text>
asda
</Text>
</View>
)
}
}
export default FrequentlyAskedQuestion;
My bad, I made a mistake in the stack navigator of importing the component, it already solved
from
import FrequentlyAskedQuestion from '../features/faq/faq';
to import FrequentlyAskedQuestion from '../features/faq/Faq';
I am making a pokedex, and from the FlatList I would like users to be able to click on a pokemon, and get directed to a detail page of the particular pokemon. However, the navigation.navigate is not working in both class and function based views. I have looked at the documentation and it uses the method I am trying to implement. What is going wrong?
App.js
import * as React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import PokedexData from './components/PokedexData';
import PokemonView from './components/PokedexData';
const Stack = createStackNavigator();
export default class App extends React.Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
options={{headerShown: false}}
name="PokedexList"
component={PokedexData}
/>
<Stack.Screen name="PokemonView" component={PokemonView} />
</Stack.Navigator>
</NavigationContainer>
);
}
}
PokedexData.js
import React, {Component} from 'react';
import axios from 'axios';
import {View, FlatList} from 'react-native';
import PodexRow from './PokedexRow';
export default class PokedexRow extends Component {
constructor(props) {
super(props);
this.state = {
pokemon: [],
};
}
componentDidMount() {
this.loadPokemon();
}
loadPokemon = () => {
axios
.get('https://pokeapi.co/api/v2/pokemon?limit=151')
.then((res) => this.setState({pokemon: res.data.results}));
};
renderItem = ({item}) => <PodexRow name={item.name} />;
render() {
return (
<FlatList
data={this.state.pokemon}
renderItem={this.renderItem}
keyExtractor={(item) => item.url}
/>
);
}
}
PokedexRow.js
import {View, StyleSheet, Text, Pressable} from 'react-native';
export default class PokedexRow extends Component {
constructor(props) {
super(props);
}
onPressHandle = () => {
alert(this.props.name);
const {navigate} = this.props.navigation;
};
render() {
return (
<View style={styles.PokedexRowView}>
<Pressable
style={styles.PokedexClickable}
onPress={this.onPressHandle}
android_ripple={{color: 'gray'}}>
<Text style={styles.PokedexRowText}>{this.props.name}</Text>
</Pressable>
</View>
);
}
}
const styles = StyleSheet.create({
/*stles removed for brevity*/
});
Because PokedexRow is not a screen where you get the navigation prop automatically. you can use useNavigation for a functional component to get access to navigation object or pass navigation from screen component to your PokedexRow as a prop.
renderItem = ({item}) => <PodexRow navigation={this.props.navigation} name={item.name} />;
I am getting an error, 'Attempted to assign to readonly property'. I am not sure how to decipher this error message and I feel like my logic looks ok. I am not quite sure where to look.
container component:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import { Image } from './Image.js'
import { Button } from './Button.js'
const images = ['https://uploads3.wikiart.org/images/wladyslaw-strzeminski/cover-for-a-book-by-julian-przybo-z-ponad-1930.jpg!Large.jpg',
'https://uploads6.wikiart.org/images/pablo-picasso/girl-on-the-ball-1905.jpg!Large.jpg',
'https://uploads8.wikiart.org/images/salvador-dali/et-post-buccellam-introivit-in-eum-satanas-psalms-40-10-1964.jpg']
class Game extends React.Component{
constructor(props){
super(props)
this.state = {
currentImg: 0
}
this.handleClick = this.handleClick.bind(this)
}
handleClick(){
const current = this.state.currentImg; <--------- error points to this
const next = ++current % images.length;
this.setState({
currentImg: next
})
}
render(){
let src = this.state.currentImg;
return(
<div>
<Image src={images[src]} />
<Button onClick={this.handleClick} />
</div>
)
}
}
ReactDOM.render(
<Game />,
document.getElementById('root')
);
presentational components:
Button:
import React from 'react';
export const Button = (props) => {
return <button onClick={props.onClick}></button>
}
Image:
import React from 'react';
export const Image = (props) => {
return (
<div className="flex-main-item">
<img className="mainImage" src={props.src} />
</div>
)
}
I am using Redux Form to capture user info submission. I've connected Redux Form with the store and written the form according to the instructions, but when clicking the submit button, no values are passed through.
I do not usually ask on Stack Overflow so please excuse for my bad wording. I do not know how to articulate my problem.
I copied my code on to snack expo (link: https://snack.expo.io/S1_6f7dQV)
Here are my codes:
Components/Form.js
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import { StyleSheet, View, Text, TouchableOpacity, TextInput } from 'react-native';
const renderField = ({ label, keyboardType, name }) => {
return (
<View>
<Text>{label}</Text>
<TextInput keyboardType={keyboardType}
>
</TextInput>
</View>
);
};
const submit = values => {
alert(`here is the value ${JSON.stringify(values)}`)
}
const ContactComponent = props => {
const { handleSubmit } = props;
console.log('handle submit ...');
console.log(handleSubmit);
return (
<View>
<Text>Redux-form example</Text>
<Field keyboardType="default" label="Username: " component={renderField} name="Username" />
<Field keyboardType="email-address" label="Email: " component={renderField} name="Email" />
<TouchableOpacity onPress={handleSubmit(submit)} style={{ margin: 10, alignItems: 'center' }}>
<Text>Submit</Text>
</TouchableOpacity>
</View>
);
}
const ContactForm = reduxForm({
form: 'contact', // a unique identifier for this form
})(ContactComponent);
export default ContactForm;
Component/MainComponent.js
import { createStackNavigator, createAppContainer } from 'react-navigation';
import HomeScreen from '../screens/HomeScreen';
import React, { Component } from 'react';
import { View, Icon} from 'native-base';
const MainNavigator = createStackNavigator({
Home: { screen: HomeScreen }
// AddTransaction: { screen: AddTransaction },
// TransactionList: { screen: TransactionList }
})
const Main = createAppContainer(MainNavigator);
export default Main;
Screen/HomeScreen.js
import React, {Component} from 'react';
import { Container, View, Text, Content, Button, Form } from 'native-base';
import ContactForm from '../components/Form.js';
class HomeScreen extends Component {
static navigationOptions = {
title: 'Home',
}
render() {
return (
<Container>
<ContactForm/>
</Container>
);
}
}
export default HomeScreen;
App.js
import React from 'react';
import { View, Text } from 'native-base';
import Main from './components/MainComponent';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { createLogger } from 'redux-logger';
import { reducer as formReducer } from 'redux-form';
const rootReducer = combineReducers({
form: formReducer,
});
export const store = createStore(rootReducer)
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<Main />
</Provider>
);
}
}
Try including the input props to yout TextInput like below, as shown in the example here on ReduxForm's docs
const renderField = ({ label, keyboardType, name, input }) => {
return (
<View>
<Text>{label}</Text>
<TextInput keyboardType={keyboardType} {...input}
>
</TextInput>
</View>
);
};
I need inside the file artistPage.js to refer to the TabNavigator in index.ios.js. In particular, I need to change the styles to hide the TabBar when the user is on the page artistPage.
How can I do that? Any ideas?
I tried to transfer styles in the props but there is the read-only mode(
index.ios.js
'use strict'
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
View,
Image,
Text,
NavigatorIOS,
TouchableHighlight,
NavigationBar,
} from 'react-native';
import config from './config';
import ImagesList from './app/imagesList';
import TabNavigator from 'react-native-tab-navigator';
import Badge from './node_modules/react-native-tab-navigator/Badge'
class MyApp extends Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'images',
showTabBar: true
};
}
render() {
let tabBarStyle = {};
let sceneStyle = {};
if (this.state.showTabBar) {
tabBarStyle = styles.tabBar;
sceneStyle.paddingBottom = 54;
} else {
tabBarStyle.height = 0;
tabBarStyle.overflow = 'hidden';
sceneStyle.paddingBottom = 0;
}
return (
<View style={styles.container}>
<TabNavigator
tabBarStyle={ tabBarStyle }
sceneStyle={sceneStyle}
>
<TabNavigator.Item
titleStyle={styles.title}
selectedTitleStyle={styles.title_select}
selected={this.state.selectedTab === 'images'}
title="TATTOOS"
renderIcon={() => <Image source={require('./images/tabbar/tattoos_icon.png')} />}
renderSelectedIcon={() => <Image source={require('./images/tabbar/tattoos_icon_selected.png')} />}
onPress={() => this.setState({ selectedTab: 'images' })}>
<NavigatorIOS
style={styles.container}
initialRoute={{
title: 'MyApp',
component: ImagesList,
passProps: { showTabBar: true},
}}
navigationBarHidden={true}/>
</TabNavigator.Item>
</TabNavigator>
</View>
);
}
}
AppRegistry.registerComponent('MyApp', () => MyApp);
imageList.js
'use strict'
import React, { Component } from 'react';
import {
StyleSheet,
ListView,
View,
Text,
Image,
Dimensions,
ActivityIndicator,
TouchableHighlight,
RefreshControl
} from 'react-native';
import ArtistPage from './imageCard';
class ImagesList extends Component {
constructor(props) {
super(props);
this.state = {
};
}
_artistPage() {
this.props.navigator.push({
component: ArtistPage
});
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight
onPress={this._artistPage()}
>
<Text>Got to Next Page</Text>
</TouchableHighlight>
</View>
);
}
}
}
module.exports = ImagesList;
artistPage.js
'use strict'
import React, { Component } from 'react';
import {
StyleSheet,
Text,
ListView,
View,
TouchableHighlight,
Image,
} from 'react-native';
class ArtistPage extends Component {
constructor(props) {
super(props);
this.state = {
};
}
_backTo() {
this.props.navigator.pop();
}
render() {
return (
<View>
<TouchableHighlight style={{marginTop: 100, marginLeft: 50}} onPress={() => this._backTo()} >
<Text>Back {this.props.showTabBar.toString()}</Text>
</TouchableHighlight>
</View>
);
}
}
module.exports = ArtistPage;
Here is how to hide TabNavigator: https://github.com/exponentjs/react-native-tab-navigator
let tabBarHeight = 0;
<TabNavigator
tabBarStyle={{ height: tabBarHeight, overflow: 'hidden' }}
sceneStyle={{ paddingBottom: tabBarHeight }}
/>
But I don't understand how to access it from artistPage.js
Thank you!
Data flow in React is one way. What it means in practice is that, to change something that a certain component receives via props, it will need to call back into the parent component, via a function from props.
The React website has a nice intro to the concept.
In your particular case, you could have a tabBarVisible state in MyApp, and inside render, compute the style to apply to the tab bar.
MyApp also can have a method to change this state:
hideTabBar() {
this.setState({ tabBarVisible: true });
}
Now, in order to let ArtistPage toggle that, you can pass the hideTabBar function from MyApp to ArtistPage as a prop, and call it in ArtistPage in a lifecycle hook, like componentDidMount.