Redux reducer: am i mutating the state here? - redux

i have a made a calculator app and there's one line (i can see, let me know if there's any thing else) where i think I'm mutating the state and i shouldn't ? (and yes I'm using eval() to do it). is this wrong?
this line
return eval(state.replace(/x/g, '*').replace(/÷/g, '/'))
reducer:
import { NUMBER_BUTTON, EQUALS_BUTTON, CLEAR_BUTTON, DECIMAL_BUTTON } from '../actions'
export default function calc(state = '', action) {
switch (action.type) {
case NUMBER_BUTTON:
return state+=action.value
case DECIMAL_BUTTON:
if(state.indexOf('.') > -1 ){
return state
}
return state+='.'
case EQUALS_BUTTON:
if(state.length > 0){
return eval(state.replace(/x/g, '*').replace(/÷/g, '/'))
}
case CLEAR_BUTTON:
return ''
default:
return state
}
}
component code: for reference
<View style={styles.container}>
<View style={styles.result}>
<Text style={styles.totalText}>{total}</Text>
</View>
<View style={styles.row}>
<TouchableHighlight onPress={() => number('1')}>
<View style={[styles.button, this.calculatedSize()]}>
<Text style={styles.btnTxt}>1</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={() => number('2')}>
<View style={[styles.button, this.calculatedSize()]}>
<Text style={styles.btnTxt}>2</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={() => number('3')}>
<View style={[styles.button, this.calculatedSize()]}>
<Text style={styles.btnTxt}>3</Text>
</View>
</TouchableHighlight>
</View>
<View style={styles.row}>
<TouchableHighlight onPress={() => number('4')}>
<View style={[styles.button, this.calculatedSize()]}>
<Text style={styles.btnTxt}>4</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={() => number('5')}>
<View style={[styles.button, this.calculatedSize()]}>
<Text style={styles.btnTxt}>5</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={() => number('6')}>
<View style={[styles.button, this.calculatedSize()]}>
<Text style={styles.btnTxt}>6</Text>
</View>
</TouchableHighlight>
</View>
<View style={styles.row}>
<TouchableHighlight onPress={() => number('7')}>
<View style={[styles.button, this.calculatedSize()]}>
<Text style={styles.btnTxt}>7</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={() => number('8')}>
<View style={[styles.button, this.calculatedSize()]}>
<Text style={styles.btnTxt}>8</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={() => number('9')}>
<View style={[styles.button, this.calculatedSize()]}>
<Text style={styles.btnTxt}>9</Text>
</View>
</TouchableHighlight>
</View>
<View style={styles.row}>
<TouchableHighlight onPress={() => number('0')}>
<View style={[styles.button, this.calculatedSize()]}>
<Text style={styles.btnTxt}>0</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={() => decimal('.')}>
<View style={[styles.btnMath, this.calculatedSize()]}>
<Text style={styles.btnTxt}>.</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={() => number(' + ')}>
<View style={[styles.btnMath, this.calculatedSize()]}>
<Text style={styles.btnTxt}>+</Text>
</View>
</TouchableHighlight>
</View>
<View style={styles.row}>
<TouchableHighlight onPress={() => number(' - ')}>
<View style={[styles.btnMath, this.calculatedSize()]}>
<Text style={styles.btnTxt}>-</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={() => number(' ÷ ')}>
<View style={[styles.btnMath, this.calculatedSize()]}>
<Text style={styles.btnTxt}>÷</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={() => number(' x ')}>
<View style={[styles.btnMath, this.calculatedSize()]}>
<Text style={styles.btnTxt}>x</Text>
</View>
</TouchableHighlight>
</View>
<View style={styles.row}>
<TouchableHighlight onPress={() => clear()}>
<View style={[styles.btnClear, this.calculatedSize()]}>
<Text style={styles.btnTxt}>C</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={() => equals()}>
<View style={[styles.btnEquals, this.calculatedEqualsSize()]}>
<Text style={styles.btnTxt}>=</Text>
</View>
</TouchableHighlight>
</View>
</View>

That doesn't look like it. The eval() call seems to be just evaluating the return value of an expression, which should be completely self-contained
Where you are mutating state though, is in these lines:
case NUMBER_BUTTON:
return state+=action.value // <------ mutate
case DECIMAL_BUTTON:
if(state.indexOf('.') > -1 ){
return state
}
return state+='.' // <-------- mutate
The += operator is a no-no. Just change it to a + operator, since you're returning the new state, and all should be fine.

Related

React Native FlatList can't scroll

I can't scroll my child component inside the flatlist,hope someone chould help me! if you need more detail,please let me know.
<View style={{flex:1}}>
<FlatList
data={DATA}
keyExtractor={(item)=>item.key}
renderItem={({item})=>(
<View style={{flexDirection:'row'}}>
<View>
<Text>item1</Text>
</View>
<View>
<Text>item2</Text>
</View>
<View>
<Text>item3</Text>
</View>
.
.
.
</View>
</FlatList>
<View/>

React native horizontal scrollview does not scroll

Scroll view does not scroll, only shows first three items, the rest are lost.
<View style={styles.container}>
<ScrollView horizontal contentContainerStyle={{ flexGrow: 1 }}>
<View style={{ width: "33%" }}>
<TouchableOpacity style={styles.child}>
<Text>B1</Text>
</TouchableOpacity>
</View>
<View style={{ width: "33%" }}>
<TouchableOpacity style={styles.child}>
<Text>B2</Text>
</TouchableOpacity>
</View>
<View style={{ width: "33%" }}>
<TouchableOpacity style={styles.child}>
<Text>B3</Text>
</TouchableOpacity>
</View>
<View style={{ width: "33%" }}>
<TouchableOpacity style={styles.child}>
<Text>B4</Text>
</TouchableOpacity>
</View>
<View style={{ width: "33%" }}>
<TouchableOpacity style={styles.child}>
<Text>B5</Text>
</TouchableOpacity>
</View>
</ScrollView>
</View>
Here are the styles I am using
const styles = StyleSheet.create({
container: {
height: "10%",
width: "75%",
backgroundColor: "transparent",
borderRadius: 5,
borderTopWidth: 1,
borderBottomWidth: 1,
borderColor: "lightsteelblue",
display: "flex",
flexDirection: "row",
overflow: "hidden",
},
child: {
backgroundColor: "transparent",
flex: 1,
alignItems: "center",
justifyContent: "center",
},
});
I have already tried several of the solutions offered here on other posts and have not found a solution. Any contructive, good hearted criticism is welcome, thanks for your time.
This is how I can able to scroll, I've changed some css's, you can change as per your requirements
<View style={{flex: 1}}>
<ScrollView horizontal>
<View style={{flex: 1}}>
<TouchableOpacity style={styles.child}>
<Text>B1</Text>
</TouchableOpacity>
</View>
<View style={{flex: 1}}>
<TouchableOpacity style={styles.child}>
<Text>B2</Text>
</TouchableOpacity>
</View>
<View style={{flex: 1}}>
<TouchableOpacity style={styles.child}>
<Text>B3</Text>
</TouchableOpacity>
</View>
<View style={{flex: 1}}>
<TouchableOpacity style={styles.child}>
<Text>B4</Text>
</TouchableOpacity>
</View>
<View style={{flex: 1}}>
<TouchableOpacity style={styles.child}>
<Text>B5</Text>
</TouchableOpacity>
</View>
</ScrollView>
</View>
const styles = StyleSheet.create({
container: {
height: '50%',
backgroundColor: 'transparent',
borderRadius: 5,
borderTopWidth: 1,
borderBottomWidth: 1,
flexDirection: 'row',
},
child: {
backgroundColor: 'transparent',
width: 200,
height: 100,
alignItems: 'center',
justifyContent: 'center',
},
});
Here is a snack with your code that works.
https://snack.expo.io/#waheed25/horizontal-scroll-working-
Remove that flexGrow property and put width with respect to the device or a number and don't use percentage there as it was taking the width from the container.
or simply replace this code with your code.
<View style={styles.container}>
<ScrollView horizontal>
<View style={{ width: 100 }}>
<TouchableOpacity style={styles.child}>
<Text>B1</Text>
</TouchableOpacity>
</View>
<View style={{ width: 100 }}>
<TouchableOpacity style={styles.child}>
<Text>B2</Text>
</TouchableOpacity>
</View>
<View style={{ width: 100 }}>
<TouchableOpacity style={styles.child}>
<Text>B3</Text>
</TouchableOpacity>
</View>
<View style={{ width: 100 }}>
<TouchableOpacity style={styles.child}>
<Text>B4</Text>
</TouchableOpacity>
</View>
<View style={{ width: 100}}>
<TouchableOpacity style={styles.child}>
<Text>B5</Text>
</TouchableOpacity>
</View>
</ScrollView>
</View>

Alignt TouchableOpacity with flexbox in react native

I have a problem with aligning icons in TouchableOpacity in one row.
This is my code:
<View style={styles.container12}>
<View style={styles.sociaContainer}>
<TouchableOpacity style={styles.socialIcon}
onPress={() => Linking.openURL('https://www.facebook.com/JelenPivoBiH/?brand_redir=28032575448')}>
<Icon name="facebook" size={50} color="#fff" />
</TouchableOpacity>
<TouchableOpacity style={styles.socialIcon}
onPress={() => Linking.openURL('https://www.instagram.com/jelenpivo/')}>
<Icon name="instagram" size={50} color="#fff" />
</TouchableOpacity>
</View>
<Image style={styles.headerImage} source={require('../assets/images/Picture-app2.png')} />
</View>
const styles = StyleSheet.create({
socialIcon: {
alignItems: 'center',
flexDirection: 'row',
marginLeft: 50,
},
container12: {
flex: 1,
flexDirection: 'row',
marginTop: 20,
},
});
I tried every combination with flex that I know, but it's not working. For every other element it is working, but not in this case.
This is the result:
I want them on one row.
Just a simple style change made your code works. Check this
<View style={styles.container12}>
{/* <View style={styles.sociaContainer}> */}
<View style={styles.container12}>
<TouchableOpacity style={styles.socialIcon}
onPress={() => Linking.openURL('https://www.facebook.com/JelenPivoBiH/?brand_redir=28032575448')}>
<Icon name="facebook" size={50} color="#fff" />
</TouchableOpacity>
<TouchableOpacity style={styles.socialIcon}
onPress={() => Linking.openURL('https://www.instagram.com/jelenpivo/')}>
<Icon name="instagram" size={50} color="#fff" />
</TouchableOpacity>
</View>
<Image style={styles.headerImage} source={require('../assets/images/Picture-app2.png')} />
</View>
Hope this will helps you.

How to change the color of a active button only in react native

there are four buttons how to change the color of the active one being press and change it back to normal if the other button is pressed
i tried this
state = { active: styles.btn };
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', }}>
<View style={{ padding: 10 }}>
<TouchableOpacity onPress={() => {this.setState({ active: styles.btnActive })}}
style={this.state.active}>
<Text> town </Text>
</TouchableOpacity>
</View>
<View style={{ padding: 10 }}>
<TouchableOpacity onPress={() => {this.setState({ active: styles.btnActive })}}
style={this.state.active}>
<Text> hill </Text>
</TouchableOpacity>
</View>
<View style={{ padding: 10 }}>
<TouchableOpacity onPress={() => {this.setState({ active: styles.btnActive })}}
style={this.state.active}>
<Text> street </Text>
</TouchableOpacity>
</View>
<View style={{ padding: 10 }}>
<TouchableOpacity onPress={() => {this.setState({ active: styles.btnActive })}}
style={this.state.active}>
<Text> road </Text>
</TouchableOpacity>
</View>
</View>
const styles = StyleSheet.create({
btn: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
borderColor: '#dc00ff',
borderRadius: 10,
borderWidth: 1,
padding: 10,
},
btnActive: {
alignItems: 'center',
backgroundColor: '#dc00ff',
borderColor: '#dc00ff',
borderRadius: 10,
borderWidth: 1,
padding: 10,
},
});
but instead all the buttons color are changing when one button is press
In React, whenever you do a this.setState() call the component get re-rendered. You buttons are looking to this.state.active for their styles, so whenever one button is pressed, the your this.state.active is getting updated to the btnActive styles you are passing it. I would recommend that you give each button an index so that you can distiguish between the buttons more easily.
Fair warning the code below is pretty static. If you need to make this more dynamic (say you want to generate buttons based on a list or something) you'd have to use map or a for loop, but the indexing idea would remain the same.
state = { active: null };
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', }}>
<View style={{ padding: 10 }}>
<TouchableOpacity
onPress={() => {this.setState({ active: 0 })}}
style={this.state.active === 0 ? style.btnActive : style.btn }>
<Text> town </Text>
</TouchableOpacity>
</View>
<View style={{ padding: 10 }}>
<TouchableOpacity
onPress={() => {this.setState({ active: 1 })}}
style={this.state.active === 1 ? style.btnActive : style.btn }>
<Text> town </Text>
</TouchableOpacity>
</View>
<View style={{ padding: 10 }}>
<TouchableOpacity
onPress={() => {this.setState({ active: 2 })}}
style={this.state.active === 2 ? style.btnActive : style.btn }>
<Text> town </Text>
</TouchableOpacity>
</View>
<View style={{ padding: 10 }}>
<TouchableOpacity
onPress={() => {this.setState({ active: 3 })}}
style={this.state.active === 3 ? style.btnActive : style.btn }>
<Text> town </Text>
</TouchableOpacity>
</View>
</View>
The issue is that your code is using the state.active style for every button. What I'd do is store the active button index, or key, in state and then switch on that state to decide which style to use.
Life example: https://snack.expo.io/B1mPipDwr
state = {activeIndex: 0};
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', }}>
<View style={{ padding: 10 }}>
<TouchableOpacity onPress={() => {this.setState({ activeIndex: 0 })}}
style={this.state.activeIndex === 0 ? styles.btnActive : styles.btn}>
<Text> town </Text>
</TouchableOpacity>
</View>
<View style={{ padding: 10 }}>
<TouchableOpacity onPress={() => {this.setState({ activeIndex: 1 })}}
style={this.state.activeIndex === 1 ? styles.btnActive : styles.btn}>
<Text> hill </Text>
</TouchableOpacity>
</View>
<View style={{ padding: 10 }}>
<TouchableOpacity onPress={() => {this.setState({ activeIndex: 2 })}}
style={this.state.activeIndex === 2 ? styles.btnActive : styles.btn}>
<Text> street </Text>
</TouchableOpacity>
</View>
<View style={{ padding: 10 }}>
<TouchableOpacity onPress={() => {this.setState({ activeIndex: 3 })}}
style={this.state.activeIndex === 3 ? styles.btnActive : styles.btn}>
<Text> road </Text>
</TouchableOpacity>
</View>
</View>
const styles = StyleSheet.create({
btn: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
borderColor: '#dc00ff',
borderRadius: 10,
borderWidth: 1,
padding: 10,
},
btnActive: {
alignItems: 'center',
backgroundColor: '#dc00ff',
borderColor: '#dc00ff',
borderRadius: 10,
borderWidth: 1,
padding: 10,
}
});

How to align Textinput inputs on same flex row in react native ? (dynamically)

I want to set two textInputs on same row , named set 1 and set 2
<View style={{flex: 1, flexDirection: 'row'}}>
<Text style={styles.label}style= {{width : 100}}>Expiration date</Text>
<View style={styles.inputWrap}>
<TextInput style={styles.inputdate} />
</View>
<Text style={styles.label}>CVV</Text>
<View style={styles.inputWrap}>
<TextInput style={styles.inputcvv } maxLength={17} />
</View>
Please send me the css paticulat, Thanks in Advance
If you want your labels and TextInputs in the same line the code will be like this:
<View style={{flexDirection: 'row'}}>
<View style={{flex: 1, flexDirection: 'row'}}>
<Text style={{flex: 0}}>Expiration date</Text>
<TextInput style={{flex: 1}} />
</View>
<View style={{flex: 1, flexDirection: 'row'}}>
<Text style={{flex: 0}}>CVV</Text>
<TextInput style={{flex: 1}} maxLength={17} />
</View>
</View>

Resources