React Native, how to remove old style and add new - javascript

I want remove old style (Hidden) on View and set new style (InputContainer) when onPress is called.
This source adds new style, but how do I remove old style?
showNext = (id) => {
this.refs["block-" + id].setNativeProps({
style: styles.Hidden
});
id++;
this.refs["block-" + id].setNativeProps({
style: styles.InputContainer
});
}
render() {
return (
<KeyboardAvoidingView style={[styles.Container]}>
<View style={styles.InputContainer} id="block-1" ref="block-1">
<Text>Block 1</Text>
<DefaultButton onPress={() => this.showNext(1)}>Ok</DefaultButton>
</View>
<View style={styles.Hidden} id="block-2" ref="block-2">
<Text>Block 2</Text>
</View>
</KeyboardAvoidingView>
)
}
styles
const styles = StyleSheet.create({
Container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
Hidden: {
display: "none"
},
InputContainer: {
width: "80%"
}
});

I think you could do something simpler
state = {
pressed: false
}
showNext = () => {
this.setState({pressed: !this.state.pressed})
}
render() {
return (
<KeyboardAvoidingView style={[styles.Container]}>
<View style={this.state.pressed ? styles.InputContainer : styles.Hidden} id="block-1" ref="block-1">
<Text>Block 1</Text>
<DefaultButton onPress={showNext}>Ok</DefaultButton>
</View>
<View style={styles.Hidden} id="block-2" ref="block-2">
<Text>Block 2</Text>
</View>
</KeyboardAvoidingView>
)
}
it should also work dynamically:
showNext = (id) => {
this.setState({[`blockPressed-${id}`]: !this.state[`blockPressed-${id}`]})
}
and
<View style={this.state.blockPressed-1 ? stlyes.InputContainer : styles.Hidden}>
<Text>Block 1</Text>
<DefaultButton onPress={() => showNext(1)}>Ok</DefaultButton>
</View>

Related

Passing style to my custom component is not working in react native. (styles are not attached to my custom component)

I am new to react native.
I created some custom components in project. And I pass some style to them via the props but my passing styles are not attached to that components. At the first it was working correctly but suddenly I don't know what happened that my passing styles are not working.
Here is my code:
This the page where I used my custom component and passed style to that.
function StartGameScreen(props) {
const [confirmed, setConfirmed] = useState(false);
const [selectedNumber, setSelectedNumber] = useState();
const numInputHandler = (inputText) => {
setEneteredValue(inputText.replace(/[^0-9]/g, ""));
};
const confirmInput = () => {
const chosenNumber = parseInt(enteredValue);
if (isNaN(chosenNumber) || chosenNumber <= 0 || chosenNumber > 99) {
Alert.alert(
"Invalid number!",
"Number has to be a number between 0 and 99.",
[{ text: "Okay", style: "destructive", onPress: resetInput }]
);
return;
}
setConfirmed(true);
setSelectedNumber(chosenNumber);
setEneteredValue("");
Keyboard.dismiss();
};
let confirmedOutput;
if (confirmed) {
confirmedOutput = (
<Card style={styles.summeryContainer}>
<Text>You selected</Text>
<NumberContainer>{selectedNumber}</NumberContainer>
<Button
title="START GAME"
onPress={() => {
console.log("hello" + selectedNumber);
props.onStartGame(selectedNumber);
}}
/>
</Card>
);
}
return (
<TouchableWithoutFeedback
onPress={() => {
Keyboard.dismiss();
}}
>
<View style={styles.container}>
<Text style={styles.title}>Start A New Game!</Text>
*This is where I used my custom component (<Card>).*
<Card style={styles.inputContainer}>
<Text>select a number</Text>
<Input
style={styles.input}
blurOnSubmit
autoCapatilize="none"
autoCorrect={false}
keyboardType="number-pad"
maxLength={2}
onChangeText={numInputHandler}
value={enteredValue}
/>
<View style={styles.buttonCon}>
<View style={styles.button}>
<Button
title="Reset"
color={Colors.accent}
onPress={resetInput}
/>
</View>
<View style={styles.button}>
<Button
title="Confirm"
color={Colors.primary}
onPress={confirmInput}
/>
</View>
</View>
</Card>
{confirmedOutput}
</View>
</TouchableWithoutFeedback>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 10,
alignItems: "center",
},
inputContainer: {
width: 300,
maxWidth: "80%",
alignItems: "center",
},
input: {
textAlign: "center",
width: 50,
},
});
export default StartGameScreen;
And this is my Card custom component:
function Card(props) {
return (
<View style={{ ...styles.container, ...props.style }}>
{props.children}
</View>
);
}
const styles = StyleSheet.create({
container: {
shadowColor: "black",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.26,
shadowRadius: 6,
elevation: 12,
backgroundColor: "white",
padding: 20,
borderRadius: 10,
},
});
export default Card;
Change Your Card component like below then it will work
function Card(props) {
return (
<View style={[styles.container,props.style]}>
{props.children}
</View>
);
}

How can I change a button when I select a item in a flatlist

I saw some questions about it here on SO, but none of them work for me.
So my problem is when I click on the button "Add Friend" all of the buttons change to "remove", and I want to change only the button that I click
Normal
When I click in any button, all of them change to "remove"
My Code is:
export default class Friends extends Component {
state = {
visible: false,
userInfo: null,
requested: null
}
buttonAdd() {
if (this.state.requested === null) {
return (
<View style={styles.buttonContainer}>
<TouchableOpacity style={[styles.button, styles.add]} onPress={() => this.setState({ requested: true })}>
<Text style={{ color: "#fff", fontWeight: "bold" }}>Add Friend</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.remove]}>
<Text style={{ color: "#050505", fontWeight: "bold" }}>Remove</Text>
</TouchableOpacity>
</View>
)
} else if (this.state.requested === true) {
return (
<View style={styles.buttonContainer}>
<TouchableOpacity style={[styles.button, styles.remove, styles.removeBig]} onPress={() => this.setState({ requested: false })} >
<Text style={{ color: "#050505", fontWeight: "bold" }}>Remove</Text>
</TouchableOpacity>
</View>
)
} else {
return (
<View style={styles.buttonContainer}>
<TouchableOpacity style={[styles.button, styles.add]} onPress={() => this.setState({ requested: true })}>
<Text style={{ color: "#fff", fontWeight: "bold" }}>Add Friend</Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.remove]}>
<Text style={{ color: "#050505", fontWeight: "bold" }}>Remove</Text>
</TouchableOpacity>
</View>
)
}
}
render() {
const inform = this.props.info
return (
<View>
<FlatList
data={inform}
keyExtractor={item => item.id.toString()}
ListHeaderComponent={this.topComponents()} //ignore this //with the ListHeaderComponent the components will not repeat
renderItem={({ item }) => (
<View style={styles.peopleContainer}>
<TouchableOpacity onPress={() => this.setState({ visible: true, userInfo: item })}> <Image source={item.photo} style={styles.photo} />
</TouchableOpacity>
<View style={styles.geralContent}>
<Text style={styles.name}>{item.name}</Text>
{this.buttonAdd()}
</View>
</View>
)}
/>
</View>
);
}
}
Sorry about the huge code.
There may be several approaches to handle this. This is just my approach to handle this specific issue.
Currently, all of the items sharing the same state. That means if any of the items update the component state, it will affect all the items of the FlatList. To overcome this problem we need to refactor the code so every item has its own state. Here is a snippet of how to do that and fix the problem
const FriendItem = ({ item, onPressPhoto }) => {
const [requested, setRequested] = React.useState(false)
return (
<View style={styles.peopleContainer}>
<TouchableOpacity onPress={() => onPressPhoto({ visible: true, userInfo: item })}>
<Image source={item.photo} style={styles.photo} />
</TouchableOpacity>
<View style={styles.geralContent}>
<Text style={styles.name}>{item.name}</Text>
<View style={styles.buttonContainer}>
{!requested ?
<TouchableOpacity style={[styles.button, styles.add]} onPress={() => setRequested(true)}>
<Text style={{ color: "#fff", fontWeight: "bold" }}>Add Friend</Text>
</TouchableOpacity>
:
null
}
<TouchableOpacity style={[styles.button, styles.remove]}>
<Text style={{ color: "#050505", fontWeight: "bold" }}>Remove</Text>
</TouchableOpacity>
</View>
</View>
</View>
)
}
export default class Friends extends Component {
state = {
visible: false,
userInfo: null,
}
onPressPhoto = ({ visible, userInfo }) => {
//write your logic here to handle on click
}
render() {
const inform = this.props.info
return (
<View>
<FlatList
data={inform}
keyExtractor={item => item.id.toString()}
ListHeaderComponent={this.topComponents()} //ignore this //with the ListHeaderComponent the components will not repeat
renderItem={({ item }) => <FriendItem item={item} onPressPhoto={this.onPressPhoto} />}
/>
</View>
);
}
}

extend <View> according to components inside it

In my containerTop, I am rendering a list inside TripOptionsSelectorthat hides towards the end.
I have tried adding marginBottom/paddingBottom to containerOptionsSelectorbut it makes no difference. I don't want to add a height to my because it can vary according to different phones.
How else can I simply extend the View such that the text doesn't hide?
export const MapScreen: React.FunctionComponent = () => {
return (
<SafeAreaView style={styles.safeAreaViewContainer}>
<View style={styles.container}>
<View style={styles.containerTop}>
<BackArrow />
<JourneyLocationsTextContainer />
<View style={styles.containerOptionsSelector}>
<TripOptionsSelector />
</View>
</View>
<View style={styles.containerMap}>
<MapContainer />
<ButtonsContainer />
</View>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
safeAreaViewContainer: { flex: 1 },
container: { flex: 1, backgroundColor: 'white'},
containerTop: { flex: 1, backgroundColor: '#323443' },
containerOptionsSelector: {
marginTop: moderateScale(15),
marginLeft: moderateScale(20),
},
containerMap: {
flex: 2
},
});
export const TripOptionsSelector: React.FunctionComponent = () => {
return (
<View style={styles.offerContainer}>
<Text style={styles.offerText}>Jetzt</Text>
<Text style={styles.offerText}>1 Person</Text>
<Text style={styles.offerText} >Filter</Text>
</View>
);
};
const styles = StyleSheet.create({
offerContainer: {
flexDirection: 'row',
},
You just remove flex from styles.containerTop - so it's sized based purely on its content.

React Native Register Button issue

In the React Native application, the button continues to operate when the information is entered incorrectly on the member entry and registration page. The button is not activated again to re-enter information. Could you help?
In other words, when the information is entered incorrectly or missing, the registration button is rotating continuously.
Please review the screenshot and codes.
Screenshot:
[![Screen shot with the UI][1]][1]
My codes are:
import React from 'react';
import { StyleSheet, Text, View, Image, Dimensions, TextInput, TouchableOpacity, ActivityIndicator } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import Icon from 'react-native-vector-icons/Ionicons';
const { height, width } = Dimensions.get('window');
const LogoImg = require('../assets/img/challengelogo.png');
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scrollview'
import {connect} from 'react-redux';
import * as appActions from './actions';
export class signupView extends React.Component {
constructor(props){
super(props);
this.state = {
checkboxChecked: false,
checkboxIcon: 'ios-square-outline'
}
}
render() {
const { container, innerContainer, innerImageContainer, buttonView , buttonViewRegister, innerButtonTextView, innerButtonView, termsView} = styles;
return (
<LinearGradient
colors={['#f9a149', '#e86e52', '#d6375c']}
style={ container }>
<KeyboardAwareScrollView
showsVerticalScrollIndicator={false}
keyboardShouldPersistTaps="always"
style={styles.scrollContainer}>
<View style={innerContainer}>
<Image
source={LogoImg}
style={{ width: width*0.45, height: width*0.55 }}
resizeMode={'contain'}
/>
<View style={{flexDirection:'row', alignItems:'center'}}>
<Text style={{color:'#fff', fontSize:18, margin:10, textDecorationLine:'underline'}} >KAYIT OL</Text>
</View>
<View style={styles.searchSection}>
<Icon style={styles.searchIcon} name="ios-person-add" size={30} color="#000"/>
<TextInput
style={styles.input}
placeholder="Kullanıcı Adı"
underlineColorAndroid="transparent"
autoCapitalize = 'none'
autoCorrect = {false}
value = {this.props.r_name}
onChangeText={this._onNameChanged.bind(this)}
autoFocus = { true }
blurOnSubmit = { false }
returnKeyType = { "next" }
onSubmitEditing = {() => {this.mailTextInput.focus()} }
/>
</View>
<View style={styles.searchSection}>
<Icon style={styles.searchIcon} name="ios-mail-outline" size={30} color="#000"/>
<TextInput
ref={(input) => { this.mailTextInput = input; }}
style={styles.input}
placeholder="Mail Adresi"
underlineColorAndroid="transparent"
keyboardType="email-address"
autoCapitalize = 'none'
autoCorrect = {false}
value = {this.props.r_email}
onChangeText={this._onEmailChanged.bind(this)}
blurOnSubmit = { false }
returnKeyType = { "next" }
onSubmitEditing = {() => {this.passwordTextInput.focus()} }
/>
</View>
<View style={styles.searchSection}>
<Icon style={styles.searchIcon} name="md-lock" size={30} color="#000"/>
<TextInput
ref={(input) => { this.passwordTextInput = input; }}
style={styles.input}
placeholder="Şifre"
onChangeText={(searchString) => {this.setState({searchString})}}
underlineColorAndroid="transparent"
secureTextEntry={true}
autoCapitalize = 'none'
autoCorrect = {false}
value = {this.props.r_password}
onChangeText={this._onPasswordChanged.bind(this)}
/>
</View>
{ !this.props.isloadingSignup &&
<TouchableOpacity onPress={this._onSignUpPress}>
<View style={ [buttonView, buttonViewRegister]}>
<View style={innerButtonView}>
<Icon name="ios-person-add" size={30} color="#000" />
</View>
<View style={innerButtonTextView}>
<Text style={{ color:'#FFF', fontSize: 15}}>Kayıt Ol</Text>
</View>
</View>
</TouchableOpacity>
||
<TouchableOpacity>
<View style={ [buttonView, buttonViewRegister]}>
<View style={innerButtonView}>
<Icon name="ios-person-add" size={30} color="#000" />
</View>
<View style={innerButtonTextView}>
<ActivityIndicator color="white" size='small' />
</View>
</View>
</TouchableOpacity>
}
<TouchableOpacity onPress={this._onPressTerms}>
<View style={ [termsView]}>
<Icon name={this.state.checkboxChecked ? 'ios-checkbox': 'ios-square-outline'} size={30} color="#000" />
<Text style={{ color:'#FFF', fontSize: 15, marginLeft: 10}}><Text onPress={this._onPressTermsConditions } style={{ textDecorationLine: "underline"}}> Kullanım koşullarını</Text> Kabul Ediyorum.</Text>
</View>
</TouchableOpacity>
</View>
</KeyboardAwareScrollView>
</LinearGradient>
);
}
_onSignUpPress = () => {
if(this.state.checkboxChecked) {
var registerBody = {
email: this.props.r_email,
password: this.props.r_password,
password_confirmation: this.props.r_password,
name: this.props.r_name
};
this.props.dispatch(appActions.register(registerBody));
} else {
alert("Lütfen önce Kullanıcı şartlarını kabul edin.");
}
}
_onEmailChanged = (email) => {
this.props.dispatch(appActions.emailChanged(email));
}
_onNameChanged = (name) => {
this.props.dispatch(appActions.nameChanged(name));
}
_onPasswordChanged = (password) => {
this.props.dispatch(appActions.passwordChanged(password));
}
_onPressTerms = () => {
this.setState({ checkboxChecked: !this.state.checkboxChecked })
}
_onPressTermsConditions = () => {
this.props.navigator.push({
screen: 'challenge.TermsOfUse',
navigatorStyle: {
navBarHidden: true
}
});
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'flex-start',
},
scrollContainer:{
flex: 1,
},
innerContainer:{
flexDirection:'column',
alignItems:'center',
marginTop: height*0.08,
},
searchSection: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
width:width*0.7,
marginTop:7
},
searchIcon: {
paddingTop:5,
paddingBottom:5,
paddingLeft:10,
paddingRight:10
},
input: {
flex: 1,
backgroundColor: '#fff',
color: '#424242',
justifyContent:'center',
},
buttonView:{
width: width*0.7,
marginTop:20,
flexDirection:'row',
},
buttonViewRegister:{
backgroundColor:"#2b74a7"
},
innerButtonView:{
backgroundColor:'#bab9b9',
width:45,
height:42,
justifyContent:'center',
alignItems:'center'
},
innerButtonTextView:{
flex:1,
justifyContent:'center',
alignItems:'center'
},
termsView:{
width: width*0.8,
marginTop:20,
flexDirection:'row',
justifyContent:'center',
alignItems:'center'
}
});
const mapStateToProps = ({ signup }) => {
return { r_email, r_password, r_name, isloadingSignup } = signup;
};
export default connect(mapStateToProps)(signupView);
Firstly, thanks for your response. I couldn't put the codes here because it crossed the character limit. So you can review the action content from this link. http://karahankaraman.com/actions/index.js
I think you are overcomplicating your signup page. Do you really need to dispatch to redux to handle your signup logic? You might need to show us your actions.js file if this continues.
Meanwhile do this:
{ !this.props.isloadingSignup ?
<TouchableOpacity onPress={this._onSignUpPress}>
<View style={ [buttonView, buttonViewRegister]}>
<View style={innerButtonView}>
<Icon name="ios-person-add" size={30} color="#000" />
</View>
<View style={innerButtonTextView}>
<Text style={{ color:'#FFF', fontSize: 15}}>Kayıt Ol</Text>
</View>
</View>
</TouchableOpacity>
:
<View style={ [buttonView, buttonViewRegister]}>
<View style={innerButtonView}>
<Icon name="ios-person-add" size={30} color="#000" />
</View>
<View style={innerButtonTextView}>
<ActivityIndicator color="white" size='small' />
</View>
</View>
}

Where to implement my function when using map for iteration?

To iterate and add views dynamically from array, I'm using following code.
export default class CreateFeedPost extends Component {
constructor(props) {
super(props);
this.state = {
selectedImages: ["1", "2", "3"]
};
}
render() {
let animation = {};
let color = Platform.OS === "android"
? styleUtils.androidSpinnerColor
: "gray";
return (
<View style={{ flex: 1, flexDirection: "column" }}>
<View style={styles.topView}>
<View style={styles.closeButtonView}>
<TouchableHighlight
underlayColor="transparent"
style={styles.closeButton}
onPress={this._closeButtonClicked.bind(this)}
>
<Icon name="times" color="#4A4A4A" size={20} />
</TouchableHighlight>
</View>
<View style={styles.postButtonView}>
<TouchableHighlight
underlayColor="transparent"
style={styles.postButton}
onPress={this._postButtonClicked.bind(this)}
>
<Text style={styles.postButtonText}>Post</Text>
</TouchableHighlight>
</View>
</View>
<View style={styles.profileContainer}>
<View style={{ width: 65, height: 65, padding: 10 }}>
<Image
source={{ uri: global.currentUser.USER_PROFILE_PIC }}
style={styles.profileImage}
/>
</View>
<View style={[styles.middleTextView]}>
<Text style={[styles.memberName]}>
{global.currentUser.USER_NAME}
</Text>
</View>
</View>
<Animated.ScrollView
style={{ flex: 1 }}
scrollEventThrottle={1}
showsVerticalScrollIndicator={false}
{...animation}
>
<View>
<TextInput
ref="postTextInputRef"
placeholder="So, What's up?"
multiline={true}
autoFocus={true}
returnKeyType="done"
blurOnSubmit={true}
style={styles.textInput}
onChangeText={text => this.setState({ text })}
value={this.state.text}
onSubmitEditing={event => {
if (event.nativeEvent.text) {
this._sendCommentToServer(event.nativeEvent.text);
this.refs.CommentTextInputRef.setNativeProps({ text: "" });
}
}}
/>
</View>
</Animated.ScrollView>
<KeyboardAvoidingView behavior="padding">
<ScrollView
ref={scrollView => {
this.scrollView = scrollView;
}}
style={styles.imagesScrollView}
horizontal={true}
directionalLockEnabled={false}
showsHorizontalScrollIndicator={false}
decelerationRate={0}
snapToInterval={100}
snapToAlignment={"start"}
contentInset={{
top: 0,
left: 0,
bottom: 0,
right: 0
}}
>
{this.state.selectedImages.map(function(name, index) {
return (
<View style={styles.imageTile} key={index}>
<View style={styles.imageView}>
<TouchableHighlight
underlayColor="transparent"
style={styles.imageRemoveButton}
onPress={() => this._imageRemoveButtonClicked.bind(this)}
>
<Icon name="times" color="#4A4A4A" size={20} />
</TouchableHighlight>
</View>
</View>
);
})}
</ScrollView>
<TouchableHighlight
underlayColor="transparent"
style={styles.cameraButton}
onPress={this._cameraButtonClicked.bind(this)}
>
<View style={styles.cameraButtonView}>
<Icon name="camera" color="#4A4A4A" size={20} />
<Text style={styles.cameraButtonText}>Add Pic</Text>
</View>
</TouchableHighlight>
</KeyboardAvoidingView>
</View>
);
}
_closeButtonClicked() {
this.props.navigator.pop();
}
_postButtonClicked() {}
_cameraButtonClicked() {
this.props.navigator.push({
title: "All Photos",
id: "photoBrowser",
params: {
limit: 3,
selectedImages: this.state.selectedImages
}
});
}
_imageRemoveButtonClicked() {
console.log("yes do it");
}
}
I'm loading code in the render method. If I write the function imageRemoveButtonClicked outside render method, it's giving an error saying that 'Cannot read property bind of undefined'. Don't know what to do. Can some one please help me in this.
Use arrow functions and class property feature. For more information about binding patterns read this article. Try to add your method as:
export class App extends Component {
yourMapFunction = () => {
yourCode...
}
}
I believe the problem is that you are not using an arrow function as the argument to this.state.selectedImages.map(). If you want to access this inside an inner function, you should use the arrow function syntax. The standard syntax does not capture this.
this.state.selectedImages.map((name, index) => {
return (...);
})

Categories