undefined is not an object (evaluating 'Amazon.trim') In react native - react-native

I am new to react native. And I have created a form. But now its not sending data to server. when I click on Submit button. its keep throwing error like this
undefined is not an object (evaluating 'Amazon.trim')
so whats wrong with my code please help.
here is my code
export default function Add(props) {
const { navigation } = props
const data = props.route.params.data
const amazonD = data.service_details_data[0] ? data.service_details_data[0].amazon_name : ''
const [AmazonError, setAmazonError] = useState([]);
const [Amazon, setAmazon] = useState(undefined);
const validateInputs = () => {
if (!Amazon.trim()) {
setAmazonError('Please Fill The Input')
return;
}
else
{
//+++++++++++++++++++++++++++++++++=submitting form data to api start+++++++++++++++++++++++++++++++++++
{
const data = props.route.params.data
const phpid = data.service_details_data[0] ? data.service_details_data[0].id : ''
AsyncStorage.multiGet(["application_id", "created_by",'leadTagNumber']).then(response => {
fetch('https://xyztech/Android_API_CI/uploaddata/merchant_service_details', {
method: 'POST',
headers: {'Accept': 'application/json, text/plain, */*', "Content-Type": "application/json" },
// We convert the React state to JSON and send it as the POST body
body: JSON.stringify([{ some data}])
})
.then((returnValue) => returnValue.json())
.then(function(response) {
console.log(response)
Alert.alert("File uploaded");
return response.json();
});
});
// event.preventDefault();
}
//+++++++++++++++++++++++++++++++++submitting form data to api end++++++++++++++++++++++++++++++++++++++
Alert.alert("success")
return;
}
};
const handleAmazon = (text) => {
setAmazonError('')
setAmazon(text)
}
return (
<View style={{flex: 1}}>
<ScrollView style={{flex: 1,}} showsVerticalScrollIndicator={false}>
<TextInput
maxLength={30}
placeholder="Amazon *"
style={styles.inputStyle}
onChangeText={(text)=>handleAmazon(text)}
// value={Amazon}
defaultValue={amazonD}
value = {Amazon} />
<Text style={{color :'red'}}>{AmazonError}</Text>
</ScrollView>
<Button
style={styles.inputStyleB}
title="Submit"
color="#FF8C00"
onPress={() => validateInputs()}
/>
</View>
)
}
please ignore this = I am new to react native. And I have created a form. But now its not sending data to server. when I click on Submit button. its keep throwing error like this

Looks like you set Amazon to undefined in useState and then try to access it.

I have also declared such type of error but I will solve it by in the use state I have kept it empty not giving any value for use state then I will use an empty string then it solves.....

Related

Re render flat list when data change cause infinite loop React Native

I have two screens. Approve List and Approve Detail. When data approved in Approve Detail, page navigate to Approve List. Then approved data should disapear from FLatList. How to remove FlatList item when data approved? or how to re render FlatList when data change? Here is my code:
Approve List:
const Approve = ({ navigation }) => {
const [rekomendasi, setRekomendasi] = useState({})
// other code
const getRekomendasi = async (token, bagian) => {
try {
const response = await sippApi.get(`/penjaminan?bagian=${bagian}`, {
headers: {
Auth: token
}
});
setRekomendasi(response.data.data)
console.log(rekomendasi)
} catch (error) {
console.log(error)
}
}
useEffect(() => {
getToken();
getUserData()
getRekomendasi(token, userData.bagian);
}, [setToken, setUserData, rekomendasi]); // if I pass rekomendasi here, make infinite loop on api request
return (
<FlatList
onRefresh={() => onRefresh()}
refreshing={isFetching}
removeClippedSubviews
style={{ marginTop: 2 }}
data={rekomendasi}
keyExtractor={rekom => rekom.penjaminan.nomor_rekomendasi}
renderItem={({ item }) => {
return (
<TouchableOpacity onPress={() => navigation.navigate("ApproveDetail", { id: item.penjaminan.nomor_rekomendasi, bagian: userData.bagian })}>
<ApproveList
plafond={item.value}
kantor={item.nama_kantor}
nomor_rekomendasi={item.nomor_rekomendasi}
produk={item.skim}
/>
</TouchableOpacity>
)
}}
showsHorizontalScrollIndicator={false}
/>
)
}
If I pass value on second argument on UseEffect, it cause infinite loop on API request. If not, my FlatList cant re render when data change. What should I do?
Thanks for help
You have to remove the rekomendasi dependency in the useEffect to avoid infinite loop, it's only for init data :)
What is the purpose of onRefresh function in the FlatList ? Instead you could put the getRekomendasi function to trigger a new call and your data will be updated
try to separate the functions to two useEffects
useEffect(() => {
//<-- write your getToken() and getUserDate() here
getToken();
getUserData()
}, []);
useEffect(() => {
const getRekomendasi = async (token, bagian) => {
try {
const response = await sippApi.get(`/penjaminan?bagian=${bagian}`, {
headers: {
Auth: token
}
});
setRekomendasi(response.data.data)
console.log(rekomendasi)
} catch (error) {
console.log(error)
}
}
getRekomendasi(token, userData.bagian);
},[token,userData.bagian]);
Problem solved by using useFocusEffect
useFocusEffect(
React.useCallback(() => {
getRekomendasi(token, userData.bagian)
}, [token, userData.bagian])
);

React Native token issue when submit

i build an application with reactNative and Expo for front-end and django for back-end
i want take token from AsyncStorage to recognised the user, but the is an errors
Warning: An unhandled error was caught from submitForm(), [ReferenceError: Can't find variable: useState]
when i change the owner id to static value the submit works fine and show the token value on the console log not sure where is the issue exactly
import React, {useState} from 'react';
import { FieldArray, Formik } from "formik";
import axios from "axios";
import AsyncStorage from '#react-native-async-storage/async-storage';
import jwt_decode from "jwt-decode";
function AddScreen(props){
const submit = ({ type, category, amount }) => {
//here you define the token to be set
const [token, setToken] = useState();
//here you get the token from AsyncStorage
const getToken = async () => {
try {
const data = await AsyncStorage.getItem('token');
if (data !== null) {
setToken(data)
return data;
}
} catch (error) {
console.log(error);
}
};
//here you set the token
getToken()
//here you decode the token
const tokens = token;
const decoded = jwtDecode(tokens);
//here you get the id and it returns a number
const id = decoded.user_id
const config = {
headers: {
"Content-Type": "application/json",
},
};
const date = Date.now();
const owner = id;
const body = JSON.stringify({ type, category, amount, date, owner });
if (type == "" || category == "" || amount == "") {
alert("Please Enter all details");
return;
}
// 'http://192.168.8.143:8000/transactions/'
axios
.post("http://192.168.8.143:8000/transactions/", body, config)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
};
return (
<View style={{ flex: 1, backgroundColor: COLORS.gray }}>
<Formik
initialValues={{ type: "", category: "", amount: "" }}
onSubmit={(values) => {
submit(values);
}}
>
{(props) => (
<View style={styles.whitecard}>
<TextInput
style={styles.inputstyle}
placeholder="type"
onChangeText={props.handleChange("type")}
value={props.values.type}
/>
<TextInput
style={styles.inputstyle}
placeholder="category"
onChangeText={props.handleChange("category")}
value={props.values.category}
/>
<TextInput
style={styles.inputstyle}
placeholder="amount"
onChangeText={props.handleChange("amount")}
value={props.values.amount}
keyboardType="numeric"
/>
<View
style={{
margin: 10,
padding: 0,
backgroundColor: COLORS.pink,
borderRadius: 6,
}}
>
<Button
title="Submit"
color="white"
onPress={props.handleSubmit}
></Button>
</View>
</View>
)}
</Formik>
</View>
);
};
...
export default AddScreen;
the error show
Warning: An unhandled error was caught from submitForm(), [Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.]
You are not importing UseState from React. Also you need to convert your code into a react functional component.
EDIT
For your new error, you need to move the useState out of submit. It must be at the root level of the functional component. I am updating the code example below as well.
import React, {useState} from 'react';
//All your other imports
function AddScreen(props) {
const [token, setToken] = useState(null);
//Everything else remains same inside
};

React Native Workflow, handle 429 erros and data

im looking for a bit of guideness here, im working on a RN app with redux and everytime i enter a new screen on the app, must likely i have a "callinitialData" function inside my useEffect(), using axios to fetch api data to be dispatch() to the redux state.
Everything works but whenever i jump from screen to screen to fast, sometimes i get a 429 error of to many request, so i just setup the redux-persist hoping that would help reduce the amount of request,in my mind thinking that if my api data is equal to my local data, that request wouldnt be necessary to be made.
However it stays the same so i was thinking what would be the best aproach here, on login try to fetch all the data at once > store it at asyncstorage and redux, and fetch that on each screen ?
how would i be able then, if i fetch all the data on login, receive the new data sets from the api in real time?
App functionality -
Edit Profile (img, pass, email, name)
Data Forms (requeast X, submit data, edit forms)
Chat by contacts / create Group chat
Code Example
const ChatScreen = ({ auth: { user }, getChatContacts, chat: { contacts }, navigation }) => {
useEffect(() => {
getChatContacts();
}, []);
const onChatUser = async (_id, name, roomID) => {
console.log(_id, name, roomID, contacts.payload.clone)
navigation.navigate( "Message", {
_id, name, chatRoomId: roomID, allUsers: contacts.payload.clone
});
}
const renderItem = ({ item , index } ) => {
let userName = "";
item.users.map((users, index) => {
let idToCheck = users.toString() !== user._id.toString() ? users : false;
if (idToCheck) {
let getOneUser = contacts.payload.clone.find(x => x._id === idToCheck);
userName += "" + getOneUser.name + ", ";
}
})
return (<TouchableOpacity key={item._id} onPress={() => onChatUser(item._id, item.name, item.roomID)}>
<View style={styles.chatContainer}>
<FontAwesome name="user-circle-o" size={50} color="#000000"/>
<Text style={styles.chatTitle}>{ ((userName).length > 32) ?
(((userName).substring(0,32-3)) + '...') :
userName }</Text>
<FontAwesome name="angle-right" size={25} color="#000000"/>
</View>
</TouchableOpacity>)
};
return (
<SafeAreaView style={styles.container}>
<TextInput
autoCapitalize="none"
autoCorrect={false}
clearButtonMode="always"
placeholder="Search friend"
style={styles.chatsearch}
/>
{contacts ?
(<FlatList
data={contacts.payload.allContact}
renderItem={(item, index) => renderItem(item, index)}
keyExtractor={item => item.id}
style={styles.FlatListContainer}
/>) : (<Text style={styles.FlatListContainer}></Text>)
}
</SafeAreaView>
);
}
const styles = StyleSheet.create({});
ChatScreen.propTypes = {
isAuthenticated: PropTypes.bool,
auth: PropTypes.object,
};
const mapStateProps = state => ({
auth: state.auth,
chat: state.chat
});
export default connect(mapStateProps, {getChatContacts} )(ChatScreen);
Redux Action
export const getChatContacts = () => async dispatch => {
const config = {
header: {
"Content-Type": "application/json"
}
}
try {
const res = await axios.get(API_LINK +"/users/getChatContacts",);
dispatch({
type: GET_CONTACT_CHAT,
payload: res.data
});
} catch (err){
console.log(err)
dispatch({
type: ERROR_FAMILY_PARENT,
payload: { msg: err.response, status: err.response}
});
}
};

How to store API response in state And pass this response value to another screen as params in react native

I am new to react native. I have created A screen. Where I am getting response from API. but now I want to store that response in state. and I want to send that value to another screen by navigation params.
my response is like this ->
Array [
Object {
"phpid": 10,
},
]
here is my code
constructor(props) {
super(props);
this.state={
};
}
fetch('https://xuz.tech/Android_API_CI/uploaddata/t_details?query=', {
method: 'POST',
headers: {'Accept': 'application/json, text/plain, */*', "Content-Type": "application/json" },
body: JSON.stringify([{"==some values=="}])
})
.then((returnValue) => returnValue.json())
.then(function(response) {
console.log(response)
return response.json();
render(){
return (
<View style={{flex: 1}}>
color="black" onPress={() => this.props.navigation.navigate("FormItems",{i want to send value to formitems})} />
</View>
)}
Set your state once you receive your response, then use your state as params when navigating. Once your fetch has been resolved:
this.setState({ response: response.json() });
Sending params to another screen is fairly simple, you just need to pass an object as the second parameter to navigate.
this.props.navigation.navigate('FormItems', {
form: this.state.response,
});
The receiving component will then need to read those params:
class DetailsScreen extends React.Component {
render() {
const { navigation } = this.props;
return (
<Text>{JSON.stringify(navigation.getParam('form', 'some default'))}</Text>
}
}
A full explanation on how to use params with react-navigation v4 can be found here: https://reactnavigation.org/docs/4.x/params
Use it like this. first initialise the state and when you get data from api set the data in state and when button press pass the data to new screen in params.
import React, { Component } from 'react';
import { Text, View } from 'react-native';
export default class Example extends Component {
state = {
data: [], // initialize empty state
};
componentWillMount() {
this.requestData();
}
requestData = () =>{
fetch('https://xuz.tech/Android_API_CI/uploaddata/t_details?query=', {
method: 'POST',
headers: {'Accept': 'application/json, text/plain, */*', "Content-Type": "application/json" },
body: JSON.stringify([{"==some values=="}])
})
.then((returnValue) => returnValue.json())
.then(function(response) {
this.setState({
data:response //set data in state here
})
})
}
render() {
return (
<View style={{ flex: 1 }}>
<Button
color="black"
onPress={() =>
this.props.navigation.navigate('FormItems', {
data: this.state.data, // pass data to second screen
})
}
/>
</View>
);
}
}

Fetching Image from Server with a React Native App

I'm building a mobile app with a Springboot Rest API backend and a React-Native Frontend.
I'm able to upload a picture from the react-native API to Springboot API and to store it in my postgres database as byte[].
I'm able to retrieve this picture with a simple Get Request tested by Postman.
BUT I'm not able to fetch this image and to display it in my React Native app.
I understood there is a problem to use blob file immediately with react native but I didnt see how to handle it.
Here is my fetch function :
export const getAquariumPicture = async (
aquariumId: string
): Promise<ImageSourcePropType | any> => {
const suffixUrl = "api/downloadAquariumPicture/";
const urlService = urlServer + suffixUrl + aquariumId;
try {
const token = await getData("token");
const response = await fetch(urlService, {
method: "GET",
headers: {
Authorization: token
}
});
return response;
} catch (error) {
console.error(error);
}
};
how can I use this response to pass it as source in an Image balise ?
Here how I'm trying to use the photo :
if (rootStore.tankStore.tankImageState === "pending") {
rootStore.tankStore.storeGetImageTank();
}
const photo = rootStore.tankStore.tankPicture;
console.log("photo = " + photo);
return (
<TouchableOpacity onPress={() => choosePicture()}>
<Image source={cameraIcon} style={styles.icon} />
{photo != null ? (
<Image source={photo} style={styles.photo} />
) : (
<ActivityIndicator />
)}
</TouchableOpacity>
);
In fact I found a solution :
<Image
source={getAquariumImageSource(RootStore.tankStore.tankList[0].id)}
style={styles.photo}
/>
export const getAquariumImageSource = (id: string): ImageSourcePropType => {
return {
uri: `${urlServer}api/downloadAquariumPicture/${id}`,
method: "GET",
headers: {
Pragma: "no-cache",
Authorization: RootStore.memberStore.token
},
cache: "reload"
};
};