Reputation: 870
I am trying to change a state by using this.setSTate
but the app hangs and the state keeps on setting, until the app crashes, please what may be wrong, I am trying to set the state in the textbar
function, The name of the state is attached
. This is my code below
type Props = {};
export default class NewNote extends Component<Props> {
static navigationOptions = {
header: null,
drawerLockMode: 'locked-closed'
};
constructor(props) {
super(props);
this.state = {
photoPermission: '',
songs: [],
loaded: true,
loading: false,
new_Press: false,
text: '',
selection: [0,0],
pressed: false,
boldButton: false,
underlineButton: false,
italicButton: false,
attached: ''
};
this.textBar = this.textBar.bind(this);
}
componentDidUpdate(){
if(this.state.pressed){
this.TextInput.focus();
}
}
textinputter(){
this.setState({pressed: true});
}
textBar(){
const B = (props) => <Text style={{fontWeight: 'bold'}}>{props.children}</Text>
const {selection: [start, end], text, pressed, boldButton} = this.state
const texted = text;
if(texted){
if((start || start == 0) && (boldButton) && end!= 0){
const attacher = text.substring(0, start)+"{b}"
+text.substring(start, end)+"{/b}"+text.substring(end, text.length);
this.setState({attached: attacher},); // this state keeps on setting until the app crashes
return(
<Text style={styles.text}>{text.substring(0, start)}
<B>{text.substring(start, end)}</B>
{text.substring(end, text.length)}</Text>
);
}else{
return(
<Text style={styles.text}>{text}</Text>
);
}
}else{
// this.setState({pressed: false});
return(
<Text style={styles.placeholder}>Your Note...</Text>
); } }
onSelectionChange = event => {
const selection = event.nativeEvent.selection;
this.setState({
selection: [selection.start, selection.end]
});
};
render() {
const B = (props) => <Text style={{fontWeight: 'bold'}}>{props.children}</Text>
const I = (props) => <Text style={{fontStyle: 'italic'}}>{props.children}</Text>
const U = (props) => <Text style={{textDecorationLine: 'underline'}}>{props.children}</Text>
const {selection: [start, end], text, pressed} = this.state;
const selected = text.substring(start, end);
return (
<View style={{flex: 1, backgroundColor: '#DDDBC7',
flexDirection: 'column', }}>
<View style={{flexDirection: 'row', backgroundColor: 'transparent',
height: 20, width: (Dimensions.get('window').width)*(85.1/100),
justifyContent: 'space-between', alignItems: 'center', alignSelf: 'center',
marginTop: 52+StatusBar.currentHeight}}>
<TouchableWithoutFeedback onPress={() => this.props.navigation.goBack()}>
<View style={{width: 14, height: 20,
alignItems: 'center', justifyContent: 'center'}}>
<Image resizeMode="contain"
style={{width: 12, height: 20}}
source={require('../back.png')}/>
</View></TouchableWithoutFeedback>
<Text style={{color: 'rgba(0, 0, 0, 0.3)', fontFamily: 'zsBold',
fontSize: 16}}>
Save
</Text>
<Text style={{color: 'black', fontFamily: 'zsBold',
fontSize: 16}}>
Add
</Text>
</View>
<ScrollView contentContainerstyle={{
flexGrow: 1,
}}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
automaticallyAdjustContentInsets={false}
directionalLockEnabled={true}
bounces={false}
scrollsToTop={false}>
<TextInput
underlineColorAndroid={'transparent'}
allowFontScaling={false}
placeholder="The Title"
placeholderStyle={{fontFamily: 'ZillaSlab-Bold',
fontSize: 16,}}
placeholderTextColor="rgba(0, 0, 0, 0.2)"
style={{
paddingLeft: 28,
width: (Dimensions.get('window').width),
backgroundColor: 'transparent',
fontSize: 16, color: 'black',
borderTopWidth: 2, borderBottomWidth: 2, borderColor: 'black',
marginTop: 100, flexDirection: 'row', alignItems: 'center', fontFamily: 'ZillaSlab-Bold',
}}/>
{pressed?
<TextInput
value={text} onSelectionChange={this.onSelectionChange}
onChangeText={text => this.setState({text})}
underlineColorAndroid={'transparent'}
placeholder="Your Note..."
multiline={true}
selectionColor={'yellow'}
ref={(input) => { this.TextInput = input; }}
onBlur={()=>this.setState({pressed: false})}
placeholderStyle={{fontSize: 15, fontFamily: 'zsMedium',}}
placeholderTextColor="rgba(0, 0, 0, 0.2)"
style={{
paddingLeft: 28,
paddingTop: 28,
paddingRight: 28,
width: '100%',
backgroundColor: 'transparent',
fontSize: 15, fontFamily: 'zsMedium', color: 'black',
}}/>:
<TouchableWithoutFeedback
onPress={()=>this.setState({pressed: true})}>
<View style={{paddingLeft: 28,
paddingTop: 28,
paddingRight: 28,
width: '100%',
backgroundColor: 'transparent', }}>
{this.textBar()}
</View></TouchableWithoutFeedback>}
Upvotes: 1
Views: 71
Reputation: 8418
Quite common error:
Using setState
within render
(by textBar()
) causes rerender and next call to setState
(and next render
call) - infinite loop.
Use setState
within event handlers, never within [unconditional parts of] render
.
Upvotes: 5