Understanding UI State : Dynamic TextInput loses focus after each key press - react-native

Screens and navigating is fine, but getting data from users has been a struggle. Not only are the UI elements different, the means to capture input and store in state effectively across various input types is troubling me. Here is an example of what I think is a simple UX yet I cannot get the text inputs to focus correctly.
In the below example, the desire is to have a list of items within a horizontal scroll view and when i click on the arrow of an item, the screen scrolls and a form to edit the item appears with one or more text boxes. Future enhancements were to have this second panel have more fields based on the type of field from the list, but i cant even get a simple text box to work properly
I've got some code to boot, copy and paste as app.js in an expo init project and it should run
main question: how to retain focus on inputs on the detail panel
import React from "react";
import {
Dimensions,
FlatList,
SafeAreaView,
Text,
TextInput,
TouchableOpacity,
View,
} from "react-native";
const init_items = [
{ name: "start", value: 12500, type: "num" },
{ name: "end", value: 12700, type: "num" },
{ name: "time", value: 123.45, type: "time" },
];
const main_color = "#dddddd";
const _base = 3;
const _width = Dimensions.get("window").width;
export default function App() {
const [index, setIndex] = React.useState(0);
const [items, setItems] = React.useState(init_items);
const [curItem, setCurItem] = React.useState("");
const ref = React.useRef(null);
const textRef = React.useRef(null);
React.useEffect(() => {
console.log("index chsnaged?", index);
//if (!index) return;
ref.current?.scrollToIndex({ index, animated: true });
}, [index]);
React.useEffect(() => {
setIndex(curItem === "" ? 0 : 1);
}, [curItem]);
const useCurItem = () => {
if (curItem == "") return;
return items.find((item) => item.name == curItem);
};
const setCurItemValue = (value) => {
console.log("update " + curItem + " to " + value);
const new_items = items.map((item) => {
if (item.name == curItem) return { ...item, value: value };
return item;
});
console.log("new_items: ", new_items);
setItems(new_items);
};
const Button = ({ type, press }) => {
return (
<TouchableOpacity onPress={() => press(type)}>
<Text style={{ fontSize: 20, fontWeight: "900", margin: _base }}>
{type == "arrow" ? ">" : "X"}
</Text>
</TouchableOpacity>
);
};
const ListPanel = () => {
return (
<View>
{items.map((item) => {
return (
<View
key={item.name}
style={{
margin: _base,
}}
>
<Text style={{ fontWeight: "600", margin: _base }}>
{item.name}
</Text>
<View
style={{
alignItems: "center",
backgroundColor: "white",
borderRadius: _base,
flexDirection: "row",
justifyContent: "space-between",
margin: _base,
padding: _base,
}}
>
<Text>{item.value}</Text>
<Button type="arrow" press={() => setCurItem(item.name)} />
{/* <EmojiButton
name={"fat_arrow"}
onPress={() => setCurItem(item.name)}
size={20}
/> */}
</View>
</View>
);
})}
</View>
);
};
const DetailPanel = () => {
let thisItem = useCurItem();
if (!thisItem) return null;
return (
<View style={{ width: "100%" }}>
{/* <EmojiButton name="arrow_left" onPress={() => setCurItem("")} /> */}
<Button type="cancel" press={() => setCurItem("")} />
<Text>{curItem}</Text>
<Text>{thisItem?.value}</Text>
<Text>{thisItem.type}</Text>
{thisItem.type == "num" && (
<TextInput
ref={textRef}
onChangeText={(text) => setCurItemValue(text)}
// onSubmitEditing={() => textRef.current.focus()}
style={{ backgroundColor: "white", margin: 2 }}
value={thisItem.value.toString()}
/>
)}
</View>
);
};
const screens = [
{ name: "listing", panel: <ListPanel /> },
{ name: "detail", panel: <DetailPanel /> },
];
return (
<View style={{ marginTop: 30 }}>
<Text>Sample sliding inputs</Text>
<FlatList
bounces={false}
horizontal
keyExtractor={(item) => item.name}
ref={ref}
showsHorizontalScrollIndicator={false}
data={screens}
renderItem={({ item, index: fIndex }) => {
console.log("rendering " + item);
return (
<View
style={{
backgroundColor: main_color,
height: 300,
width: _width,
padding: _base,
}}
>
<Text> {item.name}</Text>
{item.panel}
</View>
);
}}
/>
<Text>index: {index}</Text>
<Text>curItem: {curItem}</Text>
<TouchableOpacity onPress={() => setCurItem("")}>
<View>
<Text>reset</Text>
</View>
</TouchableOpacity>
</View>
);
}

Related

React Native Scroll View not working with

Having an issue with my ScrollView. I use it in a couple different places in my application, and most of them are working exactly as expected.
However, in one component it is working very strangely - if I swipe quickly, it will sometimes work, but usually not, and if I swipe gently or only a small amount, it doesn't work at all. I render a couple different things inside the ScrollView, but can't work out why any of them might be causing a problem, and can't spot anything obvious that's different between the one that doesn't work and the others, so I'm really at my wits end!
I am testing it on Android.
Here's what I think are the relevant bits of code for the page, but I've also put the full code below - please let me know if there's any other detail that would be useful:
const wait = (timeout) => {
return new Promise((resolve) => setTimeout(resolve, timeout));
};
export default function PotluckStandalone(props) {
const potlucks = useSelector((state) => state.potlucks);
const potluck = potlucks.find(
({ idCode }) => idCode === props.route.params.idCode
);
const [refreshing, setRefreshing] = React.useState(false);
const onRefresh = React.useCallback(() => {
setRefreshing(true);
wait(2000).then(() => setRefreshing(false));
}, []);
const dispatch = useDispatch();
const Reply = () => {
return (
<View>
<FlatList
keyExtractor={(item, index) => index}
data={potluck.replies}
renderItem={({ item }) => (
<View>
<Card
containerStyle={{
borderRadius: 12,
borderWidth: 1,
elevation: 0,
backgroundColor: "rgba(255,255,255,0.6)",
overflow: "hidden",
}}
style={{ borderColor: "rgba(255,255,255,0.1)" }}
>
<Card.Title>{item.bringer} is bringing...</Card.Title>
<Card.Divider />
{item.bringing.map((bringItem, index) => {
return (
<Text key={index}>
{bringItem}
{index < item.bringing.length - 2 ? ", " : ""}
{index === item.bringing.length - 2 ? " and " : ""}
</Text>
);
})}
</Card>
</View>
)}
/>
</View>
);
};
if (!potluck) {
return <Text>Loading...</Text>;
} else {
return (
<ImageBackground
source={require("../images/background.png")}
style={{ width: "100%", height: "100%", alignItems: "center" }}
>
<ScrollView
style={styles.page}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}
>
<Card
containerStyle={{
borderRadius: 12,
borderWidth: 1,
elevation: 0,
backgroundColor: "rgba(255,255,255,0.6)",
overflow: "hidden",
}}
style={{ borderColor: "rgba(255,255,255,0.1)" }}
>
<Card.Title>
<Text>{potluck.potluckTitle}</Text>
</Card.Title>
<Card.Divider />
<Text>Host: {potluck.potluckHost}</Text>
<Text>Theme: {potluck.potluckTheme}</Text>
<Text>
Essentials:
{potluck.essentials.map((essential, index) => {
return (
<Text key={index}>
{" "}
{essential}
{index < potluck.essentials.length - 2 ? ", " : ""}
{index === potluck.essentials.length - 2 ? " and " : ""}
</Text>
);
})}
</Text>
<Card.Divider />
<Reply />
</Card>
<Bringing
potluck={potluck}
setReplySnack={() => setReplySnack(true)}
/>
</ScrollView>
</ImageBackground>
);
}
}
const styles = StyleSheet.create({
page: {
width: "90%",
paddingTop: 50,
paddingBottom: 250,
},
});
Full code here:
import { StatusBar } from "expo-status-bar";
import React, { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import {
ScrollView,
View,
Text,
FlatList,
RefreshControl,
SafeAreaView,
Button,
Share,
ImageBackground,
} from "react-native";
import { useDispatch } from "react-redux";
import { Card } from "react-native-elements";
import Bringing from "./Bringing";
import { updatePotluck } from "../actions/potlucks";
import { render } from "react-dom";
import { StyleSheet } from "react-native";
import Snackbar from "react-native-snackbar-component";
const wait = (timeout) => {
return new Promise((resolve) => setTimeout(resolve, timeout));
};
export default function PotluckStandalone(props) {
const potlucks = useSelector((state) => state.potlucks);
const potluck = potlucks.find(
({ idCode }) => idCode === props.route.params.idCode
);
const [refreshing, setRefreshing] = React.useState(false);
const onRefresh = React.useCallback(() => {
setRefreshing(true);
wait(2000).then(() => setRefreshing(false));
}, []);
const dispatch = useDispatch();
const [potluckSnackIsVisible, setPotluckSnackIsVisible] = useState(false);
const [replySnackVisible, setReplySnackVisible] = useState(false);
React.useEffect(() => {
props.route.params.success
? setPotluckSnackIsVisible(true)
: setPotluckSnackIsVisible(false);
}, []);
const onShare = async () => {
try {
const result = await Share.share({
message: `Join me for a potluck | whatLuck https://whatluck.netlify.app/potlucks/${potluck.idCode}`,
});
if (result.action === Share.sharedAction) {
if (result.activityType) {
// shared with activity type of result.activityType
} else {
// shared
}
} else if (result.action === Share.dismissedAction) {
// dismissed
}
} catch (error) {
alert(error.message);
}
};
const setReplySnack = () => setReplySnackVisible(true);
const Reply = () => {
return (
<View>
<FlatList
keyExtractor={(item, index) => index}
data={potluck.replies}
//style={styles.flatlist}
renderItem={({ item }) => (
<View>
<Card
containerStyle={{
borderRadius: 12,
borderWidth: 1,
elevation: 0,
backgroundColor: "rgba(255,255,255,0.6)",
overflow: "hidden",
}}
style={{ borderColor: "rgba(255,255,255,0.1)" }}
>
<Card.Title>{item.bringer} is bringing...</Card.Title>
<Card.Divider />
{item.bringing.map((bringItem, index) => {
return (
<Text key={index}>
{bringItem}
{index < item.bringing.length - 2 ? ", " : ""}
{index === item.bringing.length - 2 ? " and " : ""}
</Text>
);
})}
</Card>
</View>
)}
/>
</View>
);
};
if (!potluck) {
return <Text>Loading...</Text>;
} else {
return (
<ImageBackground
source={require("../images/background.png")}
style={{ width: "100%", height: "100%", alignItems: "center" }}
>
<ScrollView
style={styles.page}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}
>
<Card
containerStyle={{
borderRadius: 12,
borderWidth: 1,
elevation: 0,
backgroundColor: "rgba(255,255,255,0.6)",
overflow: "hidden",
}}
style={{ borderColor: "rgba(255,255,255,0.1)" }}
>
<Card.Title>
<Text>{potluck.potluckTitle}</Text>
</Card.Title>
<Card.Divider />
<Button onPress={onShare} title="Invite your friends" />
<Text>Host: {potluck.potluckHost}</Text>
<Text>Theme: {potluck.potluckTheme}</Text>
<Text>
Essentials:
{potluck.essentials.map((essential, index) => {
return (
<Text key={index}>
{" "}
{essential}
{index < potluck.essentials.length - 2 ? ", " : ""}
{index === potluck.essentials.length - 2 ? " and " : ""}
</Text>
);
})}
</Text>
<Card.Divider />
<Reply />
</Card>
<Bringing
potluck={potluck}
setReplySnack={() => setReplySnack(true)}
/>
<Snackbar
visible={potluckSnackIsVisible}
textMessage="Potluck created successfully!"
autoHidingTime={3000}
/>
<Snackbar
visible={replySnackVisible}
textMessage="Reply posted successfully!"
autoHidingTime={3000}
/>
</ScrollView>
</ImageBackground>
);
}
}
const styles = StyleSheet.create({
page: {
width: "90%",
paddingTop: 50,
paddingBottom: 250,
},
});

In React Native can I setState to an object that is in an api call?

This should be something so incredibly easy, but I'm struggling really hard on this. All I want to do is setState of id to "results.id" from my api call. Once it changes the state to what is inside of the api, I will then be able to successfully open up the filmography api. I've tested the axios fetch url by putting in a real id, and it works. So I'm basically trying to grab the id that I get from a search, and update the id state with THAT id. If I'm trying to setState in the wrong function, then by all means help me get it in the right function! (Also I know I have some sloppy code, but a lot of it is personal notes for me until I'm ready to save it for good)
import React, { useState } from "react";
import {
View,
TextInput,
Button,
Text,
ActivityIndicator,
ScrollView,
Image,
TouchableHighlight,
Alert,
} from "react-native";
import Modal from "react-native-modal";
import axios from "axios";
export default function Screen4() {
// id is a 2 digit number for specific actor const apiurl5 = "http://api.tmdb.org/3/search/person?api_key=84c329a92566be57845322a19ff707ac&query=" const apiurl4 = "/movie_credits?api_key=84c329a92566be57845322a19ff707ac&language=en-US" const apiurl3 = "https://api.themoviedb.org/3/person/" const apiurl2 = "https://api.themoviedb.org/3/movie/upcoming?api_key=84c329a92566be57845322a19ff707ac&language=en-US&page=1"; const apiurl = "http://www.omdbapi.com/?apikey=7ad73765&"; const [state, setState] = useState({ s: "Enter an actor...", id: "", results: [], selected: [], modalVisible: false, modalVisible2: false });
const search = () => {
// apiurl + "&t=" + state.s (Single Result)
// apiurl + "&s=" + state.s (Multiple Results)
axios(apiurl5 + state.s).then(({ data }) => {
//let results = [data]; ----- ******** Use this for &t= **************** -------------
//let results = data.Search; ----- ******** Use this for &s= **************** -------------
let results = data.results;
let id = state.id;
setState((prevState) => {
return { ...prevState, modalVisible: true };
}),
setState((prevState) => {
return { ...prevState, results: results };
}),
setState((prevState) => {
return { ...prevState, id: id };
}),
Alert.alert("The ID is: ", id, [
{ text: "Close", onPress: () => console.log("alert closed") },
]);
});
};
const openPopup = () => {
axios(apiurl3 + state.id + apiurl4).then(({ data }) => {
let result = data.cast;
setState((prevState) => {
return { ...prevState, modalVisible2: true };
}),
setState((prevState) => {
return { ...prevState, selected: result };
});
});
};
return (
<View style={{ flex: 1, padding: 10, justifyContent: "center" }}>
<Text>Cinemaster!</Text>
<TextInput
style={{
borderBottomWidth: 1,
borderBottomColor: "#ff0000",
marginBottom: 20,
}}
onChangeText={(text) =>
setState((prevState) => {
return { ...prevState, s: text };
})
}
onSubmitEditing={search}
value={state.s}
/>
<Button onPress={search} title="Search"></Button>
{/* key=result.imdbID -
This gives multiple search results with the &s= is in the URL
key=result -
This gives the result with the &t= is in the URL */}
<Modal
//animationType="slide"
transparent={false}
//visible={(state.modalVisible)}
animationIn="slideInRight"
animationOut="slideOutLeft"
useNativeDriver={true}
isVisible={state.modalVisible}
>
<ScrollView>
{state.results.map((results, index) => (
<TouchableHighlight key={index}>
<View style={{ flex: 1, padding: 10, justifyContent: "center" }}>
<Button title="Full Filmography" onPress={openPopup}></Button>
<Text>Gender: {results.gender}</Text>
<Text>ID: {results.id}</Text>
{results.known_for.map((k, i) => (
<TouchableHighlight
key={i}
// onPress={() => openPopup()}
>
<View>
<Text>Title: {k.title}</Text>
<Image
source={{
uri:
"https://image.tmdb.org/t/p/original/" +
k.poster_path,
}}
style={{ width: 300, height: 500 }}
resizeMode="cover"
/>
</View>
</TouchableHighlight>
))}
{/* <Text>Title: {results.gender}</Text> -----THIS ALSO WORKS----- */}
{/* {dataItems.map((item, index) => (
<div key={index}>
<h1>{item.title}</h1>
{item.content.map((c, i) => (
<div key={i}>
<img src={c.imageUrl} />
<h3>{c.title}</h3>
<h3>{c.description}</h3>
<hr />
</div>
))}
</div>
))} */}
</View>
</TouchableHighlight>
))}
<Text
onPress={() =>
setState((prevState) => {
return { ...prevState, modalVisible: false };
})
}
style={{
marginTop: 50,
color: "red",
fontSize: 40,
fontWeight: "bold",
}}
>
Close!
</Text>
</ScrollView>
</Modal>
{/* animationType in Modal can be fade, none, or slide */}
<Modal
//animationType="slide"
transparent={false}
//visible={(state.modalVisible)}
animationIn="slideInRight"
animationOut="slideOutLeft"
useNativeDriver={true}
isVisible={state.modalVisible2}
>
<ScrollView>
{state.selected.map((cast, index2) => (
<View key={index2}>
<Text>Title:{cast.title} </Text>
<Text>Overview:{cast.overview} </Text>
</View>
))}
</ScrollView>
<TouchableHighlight
onPress={() =>
setState((prevState) => {
return { ...prevState, modalVisible2: false };
})
}
>
<Text
style={{
marginTop: 50,
color: "red",
fontSize: 40,
fontWeight: "bold",
}}
>
Close!
</Text>
</TouchableHighlight>
</Modal>
</View>
);
}
API for results.id :
http://api.tmdb.org/3/search/person?api_key=84c329a92566be57845322a19ff707ac&query=tom%20hanks
API for filmography:
https://api.themoviedb.org/3/person/31/movie_credits?api_key=84c329a92566be57845322a19ff707ac&language=en-US
Attached an image, showing the ID I'm trying to setState inPhoneExample
I figured it out. I had to use a for loop in order to get the data I needed in order to then set that data. What wasn't clear to me at first, was if that was necessary or not, and if it was I assumed I had to do that in the section of my code where I was mapping things. But no, once I got a for loop going in that search function it started to make sense to me.

Change border color text input When its empty in react native

I want when text input is empty change border color to red with press button:
const post = () => {
let list = [];
if (homeAge === '') {
list.push('homeage')
}
}
<TextInput
style={[Styles.TextInput, { borderColor: list.includes('homeage') ? 'red' : '#006d41' }]}
onChangeText={(event) => homeAgeHandler(event)}
/>
<Button style={Styles.Button}
onPress={() => post()}>
<Text style={Styles.TextButton}>ثبت اطلاعات</Text>
</Button>
Use a useRef hook :
const ref=useRef(0);
const post = () => {
let list = [];
if (homeAge === '') {
list.push('homeage')
}
}
useEffect(()=>{
if(list.size==0&&ref.current)
{
ref.current.style.borderColor = "red";
}
},[list,ref]);
<TextInput ref={ref}
onChangeText={(event) => homeAgeHandler(event)}
/>
<Button style={Styles.Button}
onPress={() => post()}>
<Text style={Styles.TextButton}>ثبت اطلاعات</Text>
</Button>
Here is a simple example to validate text and change styling based on validation,
const App = () => {
const [text, setText] = useState("");
const [error, setError] = useState(false);
const validateText = () => {
if (text === "") {
setError(true);
} else {
setError(false);
}
};
return (
<View>
<TextInput style={[Styles.TextInput, { borderColor: error ? 'red' : '#006d41', borderWidth:'1px'}]}
onChangeText={setText}
/>
<Button style={Styles.Button}
onPress={validateText}>
<Text style={Styles.TextButton}>ثبت اطلاعات</Text>
</Button>
</View>
);
};
export default App;
TextInput empty:
TextInput not empty:
Use state instead.
Also, In the given example, you are trying to access the list which is the local variable of the post() method.
Here is the alternate solution:
export default function App() {
const [homeAge, setHomeAge] = useState('');
return (
<View style={styles.container}>
<TextInput
value={homeAge}
style={[
styles.textInput,
{ borderColor: !homeAge ? 'red' : '#006d41' },
]}
onChangeText={(text) => setHomeAge(text)}
/>
<Button title={'ثبت اطلاعات'} style={styles.button} onPress={() => {}} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
textInput: {
padding: 10,
borderWidth: 1,
},
});
Working example: Expo Snack

Get the input data from TextInputs which are programatically added using a button

I've a screen where there is a button to add textInputs. Any no. of inputs can be added by the user. There is another button named submit. When it is tapped, how can I get the appropriate input values. I need them in array eg: [{name1, designation1}, {name2, designation2}, ...].
Code:
App.js
export default class App extends React.Component {
state = {
myArr: []
}
_onPressOut() {
let temp = index ++
this.state.myArr.push(temp)
this.setState({
myArr: this.state.myArr
})
}
_getData() {
//how can I get the data from input values here?
}
render() {
let Arr = this.state.myArr.map((a, i) => {
return <NewComponent />
})
return (
<ScrollView>
<View style={styles.container}>
<Text>Event 1st</Text>
{ Arr }
<Text>Eventlast</Text>
</View>
<TouchableOpacity onPress={() => this._onPressOut()}>
<Text style={{ color: 'green' }}>Add New Component</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => this._getData()}>
<View style={{ backgroundColor: 'blue', marginTop: 30 }}>
<Text style={{ color: 'white', textAlign: 'center', marginVertical: 10 }}>Submit</Text>
</View>
</TouchableOpacity>
</ScrollView>
);
}
}
NewComponent.js
class NewComponent extends React.Component{
state = {
name: '',
designation: '',
}
onNameChange = (text) => {
this.setState({
name: text,
});
}
render () {
return (
<View style={{ borderTopWidth:2, borderBottomColor: 'red', paddingTop: 20, marginTop: 30 }}>
<TextInput
placeholder={'Enter Your Name'}
onChangeText={text => {
this.onNameChange(text);
// this.onPropValueChange('SignUpName', text);
}}
value={this.state.name}
style={[{borderBottomColor:'red', borderBottomWidth: 1}]}
/>
<TextInput
placeholder={'Designation'}
onChangeText={text => {
this.onDesignationChange(text);
// this.onPropValueChange('SignUpDesignation', text)
}
}
value={this.state.designation}
style={[{borderBottomColor:'red', borderBottomWidth: 1}]}
/>
</View>
);
}
}
Considering the following assumptions that,until the name is filled,the designation cannot be filled and until the one set of name and designation are filled, the next set of inputs should not be rendered,
In NewComponent.js for the destinationTextInput, make the following changes.
<TextInput
placeholder={'Designation'}
onChangeText={text => {
this.onDesignationChange(text);
// this.onPropValueChange('SignUpDesignation', text)
}
}
value={this.state.designation}
style={[{borderBottomColor:'red', borderBottomWidth: 1}]}
onBlur = {() => {this.props.onNameAndDesignationAdded(this.state.name,this.state.designation)}}
/>
And in App.js add the following
in state object, introduce a new state called resultArr as follows:
state = {
myArr: [],
resultArr : []
}
The _getData function will be as follows:
_getData(name,designation) {
//how can I get the data from input values here?
if(name,designation) {
let tempArr = this.state.resultArr;
tempArr.push({name, designation})
this.setState({resultArr : tempArr})
}
}
The NewComponent called in App.js will have a callback from the TextInput of destination input onBlur method.
let Arr = this.state.myArr.map((a, i) => {
return <NewComponent onNameAndDesignationAdded = {(name,designation) => {
this._getData(name,designation)
} } />
})

how to target exact item in react native flat list and hide something?

i am using flatList in react native . i want to hide only perticular item from the list. current when i am hiding a button every button is hidden from the list.
when i am pressing the bid now button . then all the button is hidden if success. i want to hide the particular items bid now button.
/////////////// main.js
constructor (props){
super(props);
this.state = {
access_token: null,
user : null,
biddata: [],
totalBid : null,
page: 0,
showbidmodel: false,
bidValue: '',
biditem : '',
hideButton: false
}
}
placeBid = (e) => {
if (this.state.bidValue.length < 2) {
Toast.show({
text: ' please enter a valid bid!',
position: 'top',
buttonText: 'Okay'
})
}
else {
var url = `...............`;
const { params } = this.props.navigation.state;
console.log("all paramssssssssf ---> ", params.token);
console.log("check state-------------->>>>",this.state)
var data = {
price: this.state.bidValue,
material_type: this.state.biditem.material_type,
truck_type: this.state.biditem.truck_type,
material_name: this.state.biditem.material_name,
num_of_trucks: this.state.biditem.num_of_trucks,
truck_name: this.state.biditem.truck_name,
_id: this.state.biditem._id,
weight: this.state.biditem.weight,
extra_notes: this.state.biditem.extra_notes,
order_no: this.state.biditem.order_no,
staff: 'no',
created_by: this.state.biditem.created_by
};
console.log("post body ----------------->>>>>", JSON.stringify(data))
fetch(url, {
method: "POST",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
Accept: "application / json",
Authorization: "Bearer " + params.token
}
}).then(res => res.json())
.catch(error => {
console.log("bid error :", error)
})
.then(response => {
console.log("all BID SUCCESs response---> ", response);
const SUCCESS = 'Quotation Saved'
if (response.status === SUCCESS) {
Toast.show({
text: ' SUCCESS !!!! BID is placed . ',
position: 'top',
buttonText: 'Okay'
})
this.setState({ showbidmodel: false , hideButton: true })
}
else
return;
});
}
}
renderItem = ({ item }) => {
return (
<ListItem
id={item.index}
selected={() => { alert(item + "selected")}}
onPressItem ={ this.onPressItem }
onPressDetails ={ this.onPressDetails }
title={item.index}
hideButton = {this.state.hideButton}
items = { item }
/>
);
}
return (
<View style = {styles.container}>
<View style={styles.innerContainer} >
<Header title="Home" navigation={this.props.navigation} />
<Modal
animationType="slide"
transparent={false}
visible={this.state.showbidmodel}
onRequestClose={() => {
this.setState({ showbidmodel: false });
}}>
<KeyboardAvoidingView style={styles.modalStyle}>
<View style={styles.modalInnerStyle }>
<Text style={{ color: "white", fontWeight: "bold", textAlign: "center", fontSize: 20 }}>
Place your bid Here.
</Text>
<InputLocal
placeholder=" your bid "
onChange={(e) => { this.setState({ bidValue: e }); } }
value={this.state.bidValue}
/>
<TouchableOpacity
style={styles.login}
onPress={ this.placeBid }
>
<Text style={{ color: "white", fontWeight: 'bold' }}> Submit </Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
</Modal>
{typeof this.state.biddata !== "undefined" && this.state.biddata.length > 0 ?
<FlatList
data={this.state.biddata}
keyExtractor={this.keyExtractor}
extraData={this.state}
renderItem={this.renderItem}
onEndReached = { this.loadMoreTripData }
onEndReachedThreshold = {1}
/> : <ActivityIndicator
style = {styles.loading}
size="large" color="#0000ff"
/> }
</View>
</View>
);
//////////////// listItem.js
onPressDetail = () => {
this.props.onPressDetails( this.props.items._id.$oid );
};
onPressBid = () => {
this.props.onPressItem(this.props.items._id.$oid);
};
<View style={{ flex: 1, flexDirection: 'row',}} >
<MyIcon name="airport-shuttle" />
<Text style={styles.textStyle}>Truck Type: {this.props.items.truck_type}</Text>
</View>
{ !this.props.hideButton ? (
<View style={styles.buttonView}>
<View style={styles.flex} >
<TouchableOpacity
style={styles.detail}
onPress={this.onPressDetail}
>
<Text style={{ color: "white", fontWeight: 'bold', textAlign: "center" }}> Details </Text>
</TouchableOpacity>
</View>
<View style={styles.flex} >
<TouchableOpacity
style={styles.bid}
onPress={this.onPressBid}
>
<Text style={{ color: "white", fontWeight: 'bold', textAlign: "center", backgroundColor: '#ED4C67' }}> Bid Now </Text>
</TouchableOpacity>
</View>
</View>
) : null }
</View>
You can store index of the item on which you want to hide button. For that you have to pass index in your renderItem() and from there to your ListItem
renderItem={({ item, index }) => this. renderItem(item, index)}
or
You can have variable inside your each item, which indicates to show or hide button