我是新手做出反应原生的,所以我可能会采取错误的做法,如果有的话,请随意指出更好的架构。
我正在构建一个显示5个InputText的组件。每个都只能有一个数字,所以当文本改变时,我使用onChangeText事件继续下一个TextInput。 我遇到的问题是如何设置当前关注的TextInput的样式。我将onFocus和onBlur事件触发,但是当我为样式设置state时,没有任何反应。
以下是代码:
class DigitFramedControl extends React.Component<
{},
{ showingError: boolean, errorString: string, value: string, backgroundColor: string },
> {
constructor(props: {}) {
super(props);
this.state = {
showingError: false,
errorString: 'Votre réponse est erroné. Veuillez réessayer.',
value: ' ',
};
}
handleDigitChanged(index: number, character: string) {
if (index > this.state.value.length) {
const error = new Error('index out of range');
throw error;
} else if (character.length === 0) {
// user pressed backspace, don't change the end value
// the digit is updated in the text input though
} else {
console.log('setting state');
this.setState((prevState, props) => ({
value: prevState.value.substr(0, index) + character + prevState.value.substr(index + 1),
}));
// go to next field
if (index < 4) {
this.digitTextInputAtIndex(index + 1).focus();
}
}
}
onDigitFocus = (index: number) => {
const textInput = this.digitTextInputAtIndex(index);
// this.style = [styles.digitFramedControlDigit, { backgroundColor: 'green' }];
textInput.setState({ style: [styles.digitFramedControlDigit, { backgroundColor: 'green' }] });
};
onDigitBlur = (index: number) => {
const textInput = this.digitTextInputAtIndex(index);
// this.style = [styles.digitFramedControlDigit, { backgroundColor: 'green' }];
textInput.setState({ style: [styles.digitFramedControlDigit, { backgroundColor: 'red' }] });
// this.style = [styles.digitFramedControlDigit, { backgroundColor: 'red' }];
};
digitTextInputAtIndex: TextInput = (index) => {
let returnValue = null;
switch (index) {
case 0:
returnValue = this.refs.digit0;
break;
case 1:
returnValue = this.refs.digit1;
break;
case 2:
returnValue = this.refs.digit2;
break;
case 3:
returnValue = this.refs.digit3;
break;
case 4:
returnValue = this.refs.digit4;
break;
}
return returnValue;
};
render() {
const sharedTextInputProps = {
maxLength: 1,
selectTextOnFocus: true,
selectionColor: '#ffffff00',
autoCapitalize: 'none',
};
return (
<View
style={{
flexDirection: 'column',
height: 100,
width: 300,
borderWidth: 1,
borderColor: '#090',
}}
>
<View
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
borderWidth: 1,
borderColor: '#600',
}}
>
<TextInput
{...sharedTextInputProps}
ref="digit0"
onChangeText={this.handleDigitChanged.bind(this, 0)}
onFocus={this.onDigitFocus.bind(this, 0)}
onBlur={this.onDigitBlur.bind(this, 0)}
style={[
styles.digitFramedControlDigit,
{ backgroundColor: this.state.backgroundColor },
]}
returnKeyType="next"
/>
<TextInput
ref="digit1"
style={styles.digitFramedControlDigit}
onChangeText={this.handleDigitChanged.bind(this, 1)}
returnKeyType="next"
onFocus={this.onDigitFocus.bind(this, 1)}
onBlur={this.onDigitBlur.bind(this, 1)}
style={[
styles.digitFramedControlDigit,
{ backgroundColor: this.state.backgroundColor },
]}
/>
<TextInput
ref="digit2"
style={styles.digitFramedControlDigit}
onChangeText={this.handleDigitChanged.bind(this, 2)}
onFocus={this.onDigitFocus.bind(this, 2)}
onBlur={this.onDigitBlur.bind(this, 2)}
style={[
styles.digitFramedControlDigit,
{ backgroundColor: this.state.backgroundColor },
]}
returnKeyType="next"
/>
<TextInput
ref="digit3"
style={styles.digitFramedControlDigit}
onChangeText={this.handleDigitChanged.bind(this, 3)}
onFocus={this.onDigitFocus.bind(this, 3)}
onBlur={this.onDigitBlur.bind(this, 3)}
returnKeyType="next"
/>
<TextInput
ref="digit4"
style={styles.digitFramedControlDigit}
onChangeText={this.handleDigitChanged.bind(this, 4)}
onFocus={this.onDigitFocus.bind(this, 4)}
onBlur={this.onDigitBlur.bind(this, 4)}
returnKeyType="done"
/>
</View>
<Text style={styles.digitFrameErrorString}>{this.state.errorString}</Text>
<Text style={styles.digitFrameErrorString}>{this.state.value}</Text>
</View>
);
}
}
答案 0 :(得分:1)
查看以下代码。
基本上,它将焦点字段的索引存储为focusedInput
状态。
然后,当将样式应用于每个Input
时,如果索引与聚焦索引匹配,它会有条件地应用绿色背景颜色。
注意:代码未经测试,因此需要语法错误等等!
我还重构了digitTextInputAtIndex
以大大简化它;)
class DigitFramedControl extends React.Component<
{},
{ showingError: boolean, errorString: string, value: string, backgroundColor: string },
> {
constructor(props: {}) {
super(props);
this.state = {
showingError: false,
errorString: 'Votre réponse est erroné. Veuillez réessayer.',
value: ' ',
focusedInput: null,
};
}
handleDigitChanged(index: number, character: string) {
if (index > this.state.value.length) {
const error = new Error('index out of range');
throw error;
} else if (character.length === 0) {
// user pressed backspace, don't change the end value
// the digit is updated in the text input though
} else {
console.log('setting state');
this.setState((prevState, props) => ({
value: prevState.value.substr(0, index) + character + prevState.value.substr(index + 1),
}));
// go to next field
if (index < 4) {
this.digitTextInputAtIndex(index + 1).focus();
}
}
}
onDigitFocus = (index: number) => {
this.setState({ focusedInput: index })
};
onDigitBlur = (index: number) => {
this.setState({ focusedInput: null })
};
digitTextInputAtIndex: TextInput = (index) => {
return this.refs[`digit${index}`]
};
render() {
const sharedTextInputProps = {
maxLength: 1,
selectTextOnFocus: true,
selectionColor: '#ffffff00',
autoCapitalize: 'none',
};
return (
<View
style={{
flexDirection: 'column',
height: 100,
width: 300,
borderWidth: 1,
borderColor: '#090',
}}
>
<View
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
borderWidth: 1,
borderColor: '#600',
}}
>
<TextInput
{...sharedTextInputProps}
ref="digit0"
onChangeText={this.handleDigitChanged.bind(this, 0)}
onFocus={this.onDigitFocus.bind(this, 0)}
onBlur={this.onDigitBlur.bind(this, 0)}
style={[
styles.digitFramedControlDigit,
this.state.focusedInput === 0 && { backgroundColor: 'green' }
]}
returnKeyType="next"
/>
<TextInput
ref="digit1"
onChangeText={this.handleDigitChanged.bind(this, 1)}
returnKeyType="next"
onFocus={this.onDigitFocus.bind(this, 1)}
onBlur={this.onDigitBlur.bind(this, 1)}
style={[
styles.digitFramedControlDigit,
this.state.focusedInput === 1 && { backgroundColor: 'green' }
]}
/>
<TextInput
ref="digit2"
onChangeText={this.handleDigitChanged.bind(this, 2)}
onFocus={this.onDigitFocus.bind(this, 2)}
onBlur={this.onDigitBlur.bind(this, 2)}
style={[
styles.digitFramedControlDigit,
this.state.focusedInput === 2 && { backgroundColor: 'green' }
]}
returnKeyType="next"
/>
<TextInput
ref="digit3"
onChangeText={this.handleDigitChanged.bind(this, 3)}
onFocus={this.onDigitFocus.bind(this, 3)}
onBlur={this.onDigitBlur.bind(this, 3)}
style={[
styles.digitFramedControlDigit,
this.state.focusedInput === 3 && { backgroundColor: 'green' }
]}
returnKeyType="next"
/>
<TextInput
ref="digit4"
onChangeText={this.handleDigitChanged.bind(this, 4)}
onFocus={this.onDigitFocus.bind(this, 4)}
onBlur={this.onDigitBlur.bind(this, 4)}
style={[
styles.digitFramedControlDigit,
this.state.focusedInput === 4 && { backgroundColor: 'green' }
]}
returnKeyType="done"
/>
</View>
<Text style={styles.digitFrameErrorString}>{this.state.errorString}</Text>
<Text style={styles.digitFrameErrorString}>{this.state.value}</Text>
</View>
);
}
}