I have a TextInput, and have a function named onEnterPin.
But i just couldnt reach that value. All I want is to get the value inside TextInput, and navigate to another screen if the value inside TextInput is correct
Could you help me? Btw one more question: After the pin is correct, i navigate to Home screen, and on Home screen I should have rooms(like living room etc, and items(tv, internet etc) under the room name and picture. Could you give me hint?
Here is the code
import React, { useState } from "react";
import { Text, View, Button, StyleSheet, TextInput, Alert } from "react-native";
const SplashScreen = ({ navigation }) => {
const [pin, setPin] = useState('');
const CORRECT_PIN = "5555";
const onEnterPin = (pin)=>{
if(pin === CORRECT_PIN) {
navigation.navigate("Home");
}
else{
Alert.alert("problem here")
}
};
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Welcome to Rooms Page</Text>
<Button
title="Go to HomeScreen"
onPress = {() => {
navigation.navigate("Home", {
itemId: 86,
otherParam: "anything you want here"
});
}} // go to the screen named Home
/>
<Text>PIN gir</Text>
<TextInput value={pin} style={styles.textInput} onChangeText={pin => setPin(pin)}></TextInput>
<Button
title="Enter"
onPress = {() => {
onEnterPin(value); // i guess the problem is here, what should i write
}}
/>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#307ecc',
},
textInput: {
borderWidth:.5,
height:35,
margin:12,
}
});
export default SplashScreen;
HomeScreen.js
import React from "react";
import { View, Text, Button } from "react-native";
const HomeScreen = ({ route, navigation }) => {
const { itemId } = route.params;
const { otherParam } = route.params;
return(
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go back"
onPress = {() => navigation.goBack()}
/>
<Button
title="go to example screen"
onPress={() => navigation.navigate("Example")}
/>
<Button
title="go to Home page again, using push"
onPress = {() => {
navigation.push("Home", {
itemId: Math.floor(Math.random() * 100)
}),
navigation.setParams({itemId:200}) // it updates itemId as 200, then does random number job in Math.random()
}}
/>
</View>
// Avoid using setParams to update screen options such as title etc. If you need to update options, use setOptions instead.
)
}
export default HomeScreen;
Change onEnterPin parameter from value to pin like this:
<Button
title="Enter"
onPress = {() => {
onEnterPin(pin); // <<<<<<<<<<<<<<<<
}}
/>
my Textinput has an ID and with this we can do this:
document.getElementById(id).value
to get the value of the Input.
You don't need to pass it to a function since the pin value already exists in local state:
const onEnterPin = () => {
if (pin === CORRECT_PIN) {
navigation.navigate("Home");
}
else {
Alert.alert("problem here")
}
};
and:
<TextInput value={pin} style={styles.textInput} onChangeText={setPin} />
<Button
title="Enter"
onPress={onEnterPin}
/>
As the 'pin' variable exists as a local state, you can use it in the 'onEnterPin()' method, without using a parameter.
The 'onEnterPin' method will be as:
const onEnterPin = () => {
if(pin === CORRECT_PIN) {
navigation.navigate("Home")
}
else{
Alert.alert("problem here")
}
}
Related
I am doing a project using MERN STACK in this I faced the above error.
ProductContainer.js
import React, { useState, useEffect } from 'react'
import { View, StyleSheet, ActivityIndicator, FlatList, Text} from 'react-native'
import { Container, Header, Icon, Item, Input } from 'native-base';
import ProductList from './ProductList';
import SearchedProduct from './SearchedProducts';
const data = require('../../assets/data/products.json');
const ProductContainer = () => {
const [products, setProducts ] = useState([]);
const [productsFiltered, setProductsFiltered] = useState([]);
const [focus, setFocus] = useState();
useEffect(() => {
setProducts(data);
setProductsFiltered(data);
setFocus(false);
return () => {
setProducts([])
setProductsFiltered([])
setFocus()
}
}, [])
const SearchProduct = (text) => {
setProductsFiltered(
products.filter((i) => i.name.toLowerCase().includes(text.toLowerCase()))
);
};
const openList = () => {
setFocus(true);
};
const onBlur = () => {
setFocus(flase);
};
return (
<Container>
<View style = {{ flexDirection: "row"}}>
<Input
width = "100%"
variant = "rounded"
placeholder="Search"
onFocus={openList}
onChangeText={(text) => SearchProduct(text)}
/>
</View>
{focus == true ? (
<SearchProduct
productsFiltered={productsFiltered}
/>
) : (
<View style={styles.container}>
<Text>Product Container</Text>
<View style={styles.listContainer}>
<FlatList
data={products}
numColumns={2}
renderItem={({item}) => <ProductList
key={item.brand}
item={item}/>}
keyExtractor={item => item.brand}
/>
</View>
</View>
)}
</Container>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export default ProductContainer
SearchedProducts.js
import React from 'react';
import { View, StyleSheet, Dimensions} from 'react-native'
import { Content, Left, Body, ListItem, Thumbnail, Text } from 'native-base';
const SearchedProduct = (props) => {
const { productsFiltered } = props;
return(
<Content >
{productsFiltered.length > 0 ? (
productsFiltered.map((item) => (
<ListItem
key={item._id.$oid}
avatar
>
<Left>
<Thumbnail
source={{uri: item.image ?
item.image : 'https://cdn.pixabay.com/photo/2012/04/01/17/29/box-23649_960_720.png'
}}
/>
</Left>
<Body>
<Text>{item.name}</Text>
<Text note>{item.description}</Text>
</Body>
</ListItem>
))
) : (
<View style={styles.center}>
<Text style={{ alignSelf: 'center' }}>
No products match the selected criteria
</Text>
</View>
)}
</Content>
);
};
const styles = StyleSheet.create({
center: {
justifyContent: 'center',
alignItems: 'center',
height: 100
}
})
export default SearchedProduct;
Please can anyone help me to solve this error .If you want I will provide other details of my code.
Thanks in advance
Not sure but you are using SearchProduct name as a component and at the same time as a method. Maybe try to rename changing either component name or method name to see if it works.
this code does not Display the list(places) which places i added to it using add_Button.
Generally working of this code is this that i input text into this react-native app using TextInput Component, after this i press the Add Button to add this text into a list(places), after this it automatically display all the entered text.
e.g if i enter the place by 1st time it only display that text, but if i enter another text it displays that text as well as the first one.
import React, {Component} from 'react';
import {View, TextInput, StyleSheet, Button, Text} from 'react-native';
export default class App extends Component
{
state = {
placeName: "",
places: []
};
placeNameChangeHandler=(val)=>
{
this.setState({
InputValue: val
})
};
placeSubmitHandler = () =>{
if(this.state.placeName.trim() === "")
{
return;
}
this.setState(prevState => {
return {
places : prevState.places.concat(prevState.placeName)
};
});
};
render()
{
const placesOutput = this.state.places.map((place, i) =>(
<Text key={i} backgroundColor = 'black' >{place}</Text>
));
return(
<View style={Styles.container}>
<View style = {Styles.inputContainer}>
<TextInput
placeholder = "Search place?"
value = {this.setState.placeName}
onChangeText = {this.placeNameChangeHandler}
style={Styles.placeInput}
/>
<Button
title='Add'
style = {Styles.placeButton}
onPress = {this.placeSubmitHandler}
/>
</View>
<View>{placesOutput}</View>
</View>
);
}
}
const Styles = StyleSheet.create({
container: {
flex:1,
padding: 10,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'flex-start'
},
inputContainer: {
width: "100%",
flexDirection : 'row',
justifyContent: 'space-between',
alignItems:'center'
},
placeInput: {
width: "70%"
},
placeButton: {
width: "30%"
}
})
This is not 100% correct, but I'll write it down.
This seems to happen because of setState.
First.
Change to value = {this.setState.placeName} to value = {this.state.placeName}
<TextInput
placeholder = "Search place?"
value = {this.state.placeName}
onChangeText = {this.placeNameChangeHandler}
style={Styles.placeInput}
/>
Next.
Change setState in placeNameChangeHandler
placeNameChangeHandler=(val)=>{
this.setState({
placeName: val
})
};
And
Add Initializing placeName
placeSubmitHandler=()=>{
if(this.state.placeName.trim() === "")
{
return;
}
this.setState(prevState => {
return {
places : prevState.places.concat(prevState.placeName),
placeName : ""
};
});
};
Sorry for my stupid English.
I hope you understand :)
I am trying to make a TextInput component as a child with a function which is from the parent component.
but then, I can't enter texts as usual(I have to set the cursor every after I enter 1 text )
would you mind tell me how to resolve this problem?
thank you in advance.
the parent component
import React, { useState, useEffect } from "react";
import { View, StyleSheet } from "react-native";
import TestListInputItem from "../components/TestListInputItem";
export default function HomeScreen() {
const [name, setName] = useState("");
const setInputName = (text) => {
setName(text);
};
return (
<View style={styles.container}>
<TestListInputItem name={name} setInputName={setInputName} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
},
});
the child component
import React, { useState } from "react";
import {
View,
StyleSheet,
Text,
TouchableOpacity,
TextInput,
} from "react-native";
export default function TestListInputItem(props) {
const [count, setCount] = useState(1);
function handleMakeNew() {
setCount((v) => v + 1);
}
function RenderList() {
return (
<View style={styles.list}>
<TextInput
style={styles.InputName}
value={String(props.name)}
onChangeText={(text) => {
props.setInputName(text);
}}
></TextInput>
<TouchableOpacity
onPress={() => {
handleMakeNew();
}}
style={styles.buttonAdd}
>
<Text>Add</Text>
</TouchableOpacity>
</View>
);
}
return [...Array(count).keys()].map((i) => <RenderList key={i} />);
}
const styles = StyleSheet.create({
list: {
width: "100%",
backgroundColor: "#ddd",
padding: 10,
},
InputName: {
borderWidth: 1,
height: 40,
backgroundColor: "#fff",
},
buttonAdd: {
backgroundColor: "orange",
width: 80,
height: 40,
margin: 3,
justifyContent: "center",
alignItems: "center",
alignSelf: "center",
},
});
Node: 12.18.3
React-Native: 4.10.1
Expo: 3.22.3
As I commented, the issues is that your function is creating a new array on every render resetting your state, here's a quick modification that should set you in the right direction
export default function AddItem(props) {
return (
<View style={styles.list}>
<TextInput
style={styles.InputName}
value={props.value}
onChangeText={(text) => {
props.setValue(text);
}}
></TextInput>
</View>
);
}
export default function TestListInputItem(props) {
const [list, setList] = useState([]);
const [value, setValue] = useState("");
function handleMakeNew() {
setList((v) => [...v, value]);
}
return (
<View>
{
list.map((item, i) => <View key={i}><Text>{item}</Text></View>)
}
<AddItem
value={value}
setValue={setValue}
/>
<TouchableOpacity
onPress={() => {
handleMakeNew();
}}
style={styles.buttonAdd}
>
<Text>Add</Text>
</TouchableOpacity>
</View>
)
}
This is known as cursor jumping. To avoid this, in your Input component, maintain a local state and use that state value as input value. when onChange is fired, update the local state value first and then send it to the parent component
Try this in the child component,
import React, { useState } from "react";
import {
View,
StyleSheet,
Text,
TouchableOpacity,
TextInput,
} from "react-native";
export default function TestListInputItem(props) {
const [count, setCount] = useState(1);
const [inputValue, setInputValue] = useState('');
function handleMakeNew() {
setCount((v) => v + 1);
}
const handleInput =(text) =>{
setInputValue(text)
props.setInputName(text)
}
function RenderList() {
return (
<View style={styles.list}>
<TextInput
style={styles.InputName}
value={inputValue}
onChangeText={(text) => {
handleInput(text);
}}
></TextInput>
<TouchableOpacity
onPress={() => {
handleMakeNew();
}}
style={styles.buttonAdd}
>
<Text>Add</Text>
</TouchableOpacity>
</View>
);
}
I am a newbie in react native, I am developing a video app to aid my learning curve. In the code below I have tried all I could to solve the error on the "displayModal" line, but could not. Please can anyone help me with this.
I want on image/video capture it will display on the modal and from the modal i will be able to "Discard", or "Save"(to firebase), or "Share" the image/video.
import React from 'react';
import { View, Text, Image, Modal, TouchableOpacity } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import styles from './styles';
export default ({captures=[]}) => {
state = {
isVisible: false
}
// hide show modal
displayModal(show){ ------this is where am getting the error
this.setState({isVisible: show})
}
return (
<Modal
transparent={true}
visible={this.state.isVisible}
// style={[styles.bottomToolbar, styles.galleryContainer]}
>
<View style={{backgroundColor: "#000000aa", flex: 1}}>
{captures.map(({ uri }) => (
<View style={styles.galleryImageContainer} key={uri}>
<Image source={{ uri }} style={styles.galleryImage} />
</View>
))}
</View>
<TouchableOpacity style={{justifyContent: 'center', alignItems: 'center'}}>
<Ionicons
name="close-outline"
color="white"
size={20}
onPress={() => {this.displayModal(!this.state.isVisible);}}
/>
<Text>Discard</Text>
</TouchableOpacity>
</Modal>
);
};
click here to see error image
From you code it looks like a functional component, but you are using state as class-based component, that might be the reason you are getting error :
export default ({captures=[]}) => {
state = {
isVisible: false
}
// hide show modal
displayModal(show){ ------this is where am getting the error
this.setState({isVisible: show})
}
Above code block should look like this :
export default ({captures=[]}) => {
const [state,setState] = useState({ isVisible: false })
// hide show modal
const displayModal = (show) => {
setState({isVisible: show})
}
You are mixing functional component with class component.
"this.state" and "this.setState" belong to class components and all the rest belongs to functional components.
Try to change this:
state = {
isVisible: false
}
// hide show modal
displayModal(show){ ------this is where am getting the error
this.setState({isVisible: show})
}
To this:
const [isVisible, setIsVisible] = React.useState(false);
const displayModal = show => setIsVisible(show);
In addition, in the return statement, remove the strings/words "this" and "this.state".
Requested addition:
import React, { useState } from 'react';
import { View, Text, Image, Button, Modal, TouchableOpacity } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import { storage } from './fbstorage';
import { Camera } from 'expo-camera';
import styles from './styles';
export default ({ captures = [] }) => {
const [isVisible, setIsVisible] = useState(false);
const takePicture = async () => {
const photoData = await Camera.takePictureAsync();
if (!photoData.cancelled) {
uploadImage(photoData.uri, imageName)
.then(() => {
Alert.alert("Success");
})
.catch((error) => {
Alert.alert('Error:', error.message);
});
}
}
const uploadImage = async (uri, imageName) => {
const response = await fetch(uri);
const blob = await response.blob();
var ref = storage().ref().child("images/" + imageName);
return ref.put(blob)
}
return (
<Modal
transparent={true}
visible={isVisible}
// style={[styles.bottomToolbar, styles.galleryContainer]}
>
<View style={{ backgroundColor: "#000000aa", flex: 1 }}>
{captures.map(({ uri }) => (
<View style={styles.galleryImageContainer} key={uri}>
<Image source={{ uri }} style={styles.galleryImage} />
</View>
))}
</View>
<TouchableOpacity
style={{
justifyContent: 'center',
alignItems: 'center',
marginTop: 20,
top: -20
}}
onPress={() => setIsVisible(false)}
>
<Ionicons
name="md-reverse-camera"
color="white"
size={40}
/>
<Text style={{ color: 'white' }}>Discard</Text>
</TouchableOpacity>
<Button
title='Save'
onPress={takePicture}
/>
</Modal>
);
};
This is the error I get every time I try and add something to my list.
TypeError: addItems is not a function. (In 'addItems(text)', 'addItems' is an instance of Object)
I cannot figure out what I am doing wrong. Im new to react-native so any help would be greatly appreciated.
Here is my App.js
import React, { useState } from 'react';
import { View, Text, StyleSheet, ImageBackground, FlatList } from 'react-native';
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
import { uuid } from 'uuidv4';
import Header from './Componets/Header';
import AddItem from './Componets/AddItem';
import background from './Images/sunrise-in-the-smoky-mountains.jpg';
import ListItem from './Componets/ListItem';
const App = () => {
const [item, setItems] = useState([
// {
// id: uuidv4(),
// name: ''
// },
{
id: uuidv4(),
name: "gym"
},
{
id: uuidv4(),
name: "study"
}
]);
const addItems = (text) => {
setItems(prevItems => {
return [{ id: uuidv4(), text }, ...prevItems]
})
}
const deleteItem = (id) => {
setItems(prevVal => {
return prevVal.filter(item => item.id != id)
})
}
return (
<View style={styles.container}>
<ImageBackground source={background} style={styles.image}>
<Header
title="Gotta get this done!" />
<AddItem
addItem={addItems}
/>
<FlatList
data={item}
renderItem={({ item }) => (
<ListItem item={item.name} deleteItem={deleteItem} />
)}
/>
</ImageBackground>
</View>
)
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
flex: 1,
resizeMode: "cover",
justifyContent: "center"
}
})
export default App;
Here is where I call the function and get the error.
import React, { useState } from 'react';
import { View, Text, StyleSheet, TextInput, TouchableOpacity, Button } from 'react-native';
const AddItem = ( addItems ) => {
const [text, setText] = useState("");
const onChange = (inputVal) => setText(inputVal);
return (
<View style={styles.addItemView}>
<TextInput
style={styles.inputText}
placeholder="Add item to list..."
onChangeText={onChange}
/>
<TouchableOpacity style={styles.button}>
<Button title="Add Item" onPress={() => addItems(text)} />
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
addItemView: {
flex: 1,
flexDirection: "row",
alignItems: 'center'
},
inputText: {
fontSize: 20,
backgroundColor: "white",
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
width: 250,
},
button: {
alignItems: "center",
justifyContent: "center",
height: 40,
backgroundColor: "#bbc7ad",
borderRadius: 10,
borderWidth: 2,
borderColor: "#99a191",
marginLeft: 20,
}
})
export default AddItem;
You are passing addItems function as a prop in
<AddItem
addItem={addItems}
/>
When you pass any function or value to any functional component in React you can access them only via props so to access addItems you need to access this function from the props
You can do that by following ways
Method 1
const AddItem = ( props ) => {
// We are extracting addItem function from props
const {addItem} = props
const [text, setText] = useState("");
const onChange = (inputVal) => setText(inputVal);
return (
<View style={styles.addItemView}>
<TextInput
style={styles.inputText}
placeholder="Add item to list..."
onChangeText={onChange}
/>
<TouchableOpacity style={styles.button}>
<Button title="Add Item" onPress={() => addItem(text)} />
</TouchableOpacity>
</View>
);
};
Method 2 :
const AddItem = ({addItem} ) => {
.....
return (
<View style={styles.addItemView}>
......
<TouchableOpacity style={styles.button}>
<Button title="Add Item" onPress={() => addItem(text)} />
</TouchableOpacity>
</View>
);
};
This seems to work for now. Still unclear as to why using destructuring in my original version didnt work. Please chime in if you can help with that. Thanks!
const AddItem = (props) => {
const [text, setText] = useState("");
const onChange = inputVal => setText(inputVal);
return (
<View style={styles.addItemView}>
<TextInput
style={styles.inputText}
placeholder="Add item to list..."
onChangeText={onChange}
/>
<TouchableOpacity style={styles.button}>
<Button title="Add Item" onPress={() => props.addItem(text)} />
</TouchableOpacity>
</View>
);
};