if else in react native - react-native

I am new to react native. I Have created a screen where I am using if else in function like this.
constructor(props) {
super(props);
this.state={
phpid = ''
}
}
validateInputs = (event) => {
const data = this.props.route.params.data
const { phpid } = this.state;
if (data.retail_information_data[0] != '') {
phpid == data.retail_information_data[0].id
}else{
phpid == null
}
AsyncStorage.multiGet(["application_id", "created_by"]).then(response => {
console.log(phpid)
fetch('https://njdnfech/Android_API_CI/uploaddata/tffmerchant_retail_details?query=', {
body: JSON.stringify([{phpid : phpid}])
})
.then((returnValue) => returnValue.json())
.then(function(response) {
console.log(response)
return response.json();
}
but I am getting = data.retail_information_data[0] = null or lets say empty
then according to if else my else condition that is 'phpid == null' shuld run
but even 'data.retail_information_data[0] = null' my else condition not running my console kepp saying
'TypeError: undefined is not an object (evaluating 'data.retail_information_data[0].id')'
is any problem in my if else or how to write proper if else

The below should work...
if (data && data?.retail_information_data.length) {
this.setState(phpid: data?.retail_information_data[0]?.id)
}else{
this.setState(phpid: null)
}

Try using ternary operator.
phpid = data.retail_information_data[0] ? data.retail_information_data[0].id : null

Related

React Native:How to wait till a series of setState function to return before executing the next block of code?

setState in reactnative is asynchronous and I have a series of setState statements in my code and I want the code after these setState statements execute only after all the setState returns
Code
validate = () => {
this.changedNumber();
const reg = /^[0]?[789]\d{9}$/;
if (this.state.spaceName == null || this.state.spaceName =='') {
this.setState({
error_spaceName: "Name of space is required",
})
} else if (this.state.spaceName.length < 3) {
this.setState({
error_spaceName: "Name of space should be of minimum 3 character length",
})
}
else {
this.setState({
error_spaceName: null,
})
}
if (this.state.code === null || this.state.code === '') {
this.setState({
error_phone: "Phone Number is required",
})
} else if (isValidNumber(Number(this.state.code)) === false) {
this.setState({
error_phone: "Contact number should be a Kuwait number",
})
}
else {
this.setState({
error_phone: null,
})
}
if (this.state.error == null && this.state.error_spaceName == null && this.state.error_phone == null) {
this.props.navigation.navigate("LocationScreen")
}
}
What happnes here is that
if (this.state.error == null && this.state.error_spaceName == null && this.state.error_phone == null) {
this.props.navigation.navigate("LocationScreen")
}
this part of code gets executed before all the setState returns .I want to wait till all the setStates returns before checking the conditions? What's the proper way to acheieve this?
You are't able to use was updated state after setState in one block , so because you use class components , you are able to use componentDidUpdate for solving it :
//...
componentDidUpdate(prevProps, prevState){
if (prevState.error != this.state.error
|| prevState.error_spaceName != this.state.error_spaceName
|| prevState.error_phone != this.state.error_phone){
if (this.state.error == null && this.state.error_spaceName == null && this.state.error_phone == null) {
this.props.navigation.navigate("LocationScreen")
}
}
}
//...

React Native Redux issue

I am having an issue with adding favourite functionality for e-commerce app. Getting error of undefined.enter image description here
case TOGGLE_FAVOURITE:
const exitsIndex = state.favouriteProducts.findIndex((meal) => meal.id === action.productId);
if(exitsIndex >= 0) {
return { ...state, favouriteProducts: state.favouriteProducts.filter((meal) => meal.id !== action.productId) }
} else {
const favMeal = state.availableProducts.find((meal) => meal.id === action.productId);
return { ...state, favouriteProducts: state.favouriteProducts.concat(favMeal) };
}
This is my action:
export const toggleFavourite = id => {
return { type: TOGGLE_FAVOURITE, productId: id };
};
And this is my call function:
const toggleFavouriteHandler = useCallback(() => {
dispatch(toggleFavourite(productId));
}, [dispatch, productId]);
you have to check for the initial state, when you are doing findIndex on favouriteProducts , favouriteProducts is null.
so just check if
state.favouriteProducts === null and that should work
To prevent TypeError you should check if state.favouriteProducts is undefined or null.
In this case, i would use:
case TOGGLE_FAVOURITE:
if (!state.favouriteProducts) return false; // you need this
const exitsIndex = state.favouriteProducts.findIndex((meal) => meal.id === action.productId);
if (exitsIndex >= 0) {
return { ...state, favouriteProducts: state.favouriteProducts.filter((meal) => meal.id !== action.productId) }
} else {
const favMeal = state.availableProducts.find((meal) => meal.id === action.productId);
return { ...state, favouriteProducts: state.favouriteProducts.concat(favMeal) };
}
I found different solution. Now its working
case TOGGLE_FAVOURITE:
const addedFavourite = action.product;
const id = addedFavourite.id;
const product_name = addedFavourite.product_name;
const product_image = addedFavourite.product_image;
const product_description = addedFavourite.product_description;
const product_price = addedFavourite.product_price;
const category_id = addedFavourite.category_id;
let updatedFavouriteItem = new Product(
id,
product_name,
product_image,
product_description,
product_price,
category_id,
)
if(state.items[addedFavourite.id] != null){
let updatedCartItems = { ...state.items };
delete updatedCartItems[action.product.id];
return {
...state,
items: updatedCartItems,
}
}
return{
...state,
items: {...state.items, [addedFavourite.id]: updatedFavouriteItem }
}
}
return state;
}

react-native-numeric-input change event is not triggered

I'm currently working on a react project using multiple libraries including react-native-numeric-input which for some reason have a lot of unexpected behaviours.
Last night I had everything working as it should be but when I can to take another look the numeric input + and - buttons are not responding to any of the clicks, I even added a console.log to the onChange prop to test if the value is not changing or the event is not triggered and i didn't get anything.
this the numeric input:
<NumericInput
onChange={num => {
console.log(num);
this.setState({ updateItem: num}, this.saveChangedConfigs);
console.log('input', this.state);
}}
value={this.state.updateItem}
totalWidth={configValues.inw}
totalHeight={configValues.inh}
initValue={this.state.updateItem}
inputStyle={{ backgroundColor: '#f4f4f4'}}
containerStyle={styles.updateValue}
minValue={1}
/>
these are the two methods that change the state:
saveChangedConfigs = async () => {
try {
this.props.saveConfigs({
stockpile: this.state.updateItem.toString(),
data: this.state.updateData.toString(),
delete: this.state.emptyFiles.toString(),
autoUpdate: this.state.autoUpdate.toString(),
language: this.state.language
})
await this.initConfigs();
} catch (error) {
console.log('save err', error);
}
}
and
initConfigs = async () => {
const configs = await AsyncStorage.multiGet([
'updateStockpile',
'updateData',
'emptyPhone',
'language',
'autoUpdate'
])
console.log("configs", configs)
const confs = {
stockpile: this.props.config.stockpile,
autoUpdate: this.props.config.autoUpdate,
language: this.props.config.language,
data: this.props.config.data,
delete: this.props.config.delete
}
await configs.map(conf => {
switch(conf[0]){
case 'updateStockpile': if(conf[1] !== null) confs.stockpile = conf[1]; break;
case 'updateData': if(conf[1] !== null) confs.data = conf[1]; break;
case 'emptyPhone': if(conf[1] !== null) confs.delete = conf[1]; break;
case 'language': if(conf[1] !== null) confs.language = conf[1]; break;
case 'autoUpdate': if(conf[1] !== null) confs.autoUpdate = conf[1]; break;
}
})
await this.props.initConfigs(confs);
await this.setState({
language: confs.language,
updateItem: Number(confs.stockpile),
updateData: Number(confs.data),
emptyFiles: Number(confs.delete),
autoUpdate: confs.autoUpdate
});
}
this is my initial state:
this.state = {
language: this.props.config.language,
updateItem: Number(this.props.config.stockpile),
updateData: Number(this.props.config.data),
emptyFiles: Number(this.props.config.delete),
autoUpdate: this.props.config.autoUpdate
}
Hope you guys can help me out with this or maybe suggest an alternative if you know about one.

React Native SectionList (title, data) - Search in the data field

I am trying to build Search function in SectionList. I have search inside the 'data' (second field) and not inside 'title' but I am not able to make it work.
My Data is about the Flat / resident details of an Apartment -
sectiondata =
[{"title":"GROUND FLOOR",
"data":[
{"id":"48","res_type":"owner","user_name":"Ashwani","flat_id":"1","flat_name":"001","floor_no":"GROUND FLOOR","floor_int":"0","signal_player_id":"aa","user_phone":"98855550"},
{"id":"49","res_type":"owner","user_name":"Rahul","flat_id":"2","flat_name":"002","floor_no":"GROUND FLOOR","floor_int":"0","signal_player_id":"aa","user_phone":"999999"}
]
}]
I am trying something like this but it is not working.
searchFilterFunction = (text) => {
let search = text.toLowerCase();
this.setState({
check: this.state.sectiondata.filter(
obj => obj.data['flat_name'].toLowerCase().includes(search))
});
}
How to filter data base on name? Please assist here.
Thanks.
You can try to search like this:
onChangeText(text) {
if (text.trim().length > 0) {
var temp = []
sectiondata.map((item) => {
var dataItem = {};
var brandData = [];
item.data.map((searchItem) => {
let flatName = searchItem.flat_name
if (flatName.match(text)) {
brandData.push(searchItem);
}
})
if (brandData.length > 0) {
} else {
return null;
}
dataItem.brandData = brandData;
temp.push(dataItem);
this.setState({
sectiondata: temp
})
})
} else {
this.setState({
sectiondata: this.state.tempData
})
}
}
searchFilterFunction(text) {
if( text == undefined || text == '') {
this.setState({
sectiondata: this.arrayholder
})
return;
}
if (text.trim().length > 0) {
var temp = []
this.state.sectiondata.map((item) => {
var dataItem = {};
var title = item.title;
var brandData = [];
item.data.map((searchItem) => {
let flatName = searchItem.flat_name
if (flatName.match(text)) {
brandData.push(searchItem);
}
})
if (brandData.length > 0) {
} else {
return null;
}
dataItem.title = title;
dataItem.data = brandData;
temp.push(dataItem);
this.setState({
sectiondata: temp
})
})

React-Native componentWillRecieveProps rendering issue

In my RN project, I want to achieve this.
// componentWillReceiveProps
componentWillReceiveProps = async (nextProps) => {
let { searchText, peopleTab } = this.props;
let params = {};
if (peopleTab !== nextProps.peopleTab) {
params.peopleTab = nextProps.peopleTab;
}
// here i want to pass nextProps.searchText without a condition with the params like this.
// params.searchText = nextProps.searchText
if (Object.keys(params).length > 0) {
await this.props.fetchUnfollowedPeople(params);
}
}
I want to send nextProps.searchText with params object, if there is a new value. Otherwise I want to send this.props.searchText with the params object.
The above code, if I uncomment
// params.searchText = nextProps.searchText
it gives the infinity loop. How can I achieve this?
Setting the let { searchText, peopleTab } = this.props; in componentWillReceiveProps causes the new value to be pasted
componentWillMount() {
this.searchText = this.props.searchText ;
this.peopleTab = this.props.peopleTab ;
}
componentWillReceiveProps = async (nextProps) => {
const params = [];
if (this.peopleTab !== nextProps.peopleTab) {
params['peopleTab'] = nextProps.peopleTab ;
}
if (Object.keys(params).length > 0) {
await this.props.fetchUnfollowedPeople(params);
}
}