[IMPROVEMENT] Use autoFocus rather than timeout + focus (#1071)

* autofocus replaced timout+focus

* removed inputRef

* Unnecessary focus on NewServerView when passing server as props

* Removed unnecessary code
This commit is contained in:
Tanuj Singh 2019-08-08 00:50:16 +05:30 committed by Diego Mello
parent 6a3523d6bf
commit 7b2185d361
9 changed files with 23 additions and 106 deletions

View File

@ -120,9 +120,6 @@ class CreateChannelView extends React.Component {
componentDidMount() { componentDidMount() {
const { navigation } = this.props; const { navigation } = this.props;
navigation.setParams({ submit: this.submit }); navigation.setParams({ submit: this.submit });
this.timeout = setTimeout(() => {
this.channelNameRef.focus();
}, 600);
} }
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState) {
@ -181,12 +178,6 @@ class CreateChannelView extends React.Component {
} }
} }
componentWillUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
}
onChangeText = (channelName) => { onChangeText = (channelName) => {
const { navigation } = this.props; const { navigation } = this.props;
navigation.setParams({ showSubmit: channelName.trim().length > 0 }); navigation.setParams({ showSubmit: channelName.trim().length > 0 });
@ -322,7 +313,7 @@ class CreateChannelView extends React.Component {
<ScrollView {...scrollPersistTaps}> <ScrollView {...scrollPersistTaps}>
<View style={sharedStyles.separatorVertical}> <View style={sharedStyles.separatorVertical}>
<TextInput <TextInput
ref={ref => this.channelNameRef = ref} autoFocus
style={styles.input} style={styles.input}
label={I18n.t('Channel_Name')} label={I18n.t('Channel_Name')}
value={channelName} value={channelName}

View File

@ -32,12 +32,6 @@ export default class ForgotPasswordView extends React.Component {
isFetching: false isFetching: false
} }
componentDidMount() {
this.timeout = setTimeout(() => {
this.emailInput.focus();
}, 600);
}
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState) {
const { email, invalidEmail, isFetching } = this.state; const { email, invalidEmail, isFetching } = this.state;
if (nextState.email !== email) { if (nextState.email !== email) {
@ -52,12 +46,6 @@ export default class ForgotPasswordView extends React.Component {
return false; return false;
} }
componentWillUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
}
validate = (email) => { validate = (email) => {
if (!isValidEmail(email)) { if (!isValidEmail(email)) {
this.setState({ invalidEmail: true }); this.setState({ invalidEmail: true });
@ -99,7 +87,7 @@ export default class ForgotPasswordView extends React.Component {
<SafeAreaView style={sharedStyles.container} testID='forgot-password-view' forceInset={{ vertical: 'never' }}> <SafeAreaView style={sharedStyles.container} testID='forgot-password-view' forceInset={{ vertical: 'never' }}>
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold]}>{I18n.t('Forgot_password')}</Text> <Text style={[sharedStyles.loginTitle, sharedStyles.textBold]}>{I18n.t('Forgot_password')}</Text>
<TextInput <TextInput
inputRef={(e) => { this.emailInput = e; }} autoFocus
placeholder={I18n.t('Email')} placeholder={I18n.t('Email')}
keyboardType='email-address' keyboardType='email-address'
iconLeft='mail' iconLeft='mail'

View File

@ -73,12 +73,6 @@ class LoginView extends React.Component {
this.setTitle(Site_Name); this.setTitle(Site_Name);
} }
componentDidMount() {
this.timeout = setTimeout(() => {
this.usernameInput.focus();
}, 600);
}
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
const { Site_Name, error } = this.props; const { Site_Name, error } = this.props;
if (nextProps.Site_Name && nextProps.Site_Name !== Site_Name) { if (nextProps.Site_Name && nextProps.Site_Name !== Site_Name) {
@ -87,11 +81,6 @@ class LoginView extends React.Component {
if (nextProps.error && nextProps.error.error === 'totp-required') { if (nextProps.error && nextProps.error.error === 'totp-required') {
LayoutAnimation.easeInEaseOut(); LayoutAnimation.easeInEaseOut();
this.setState({ showTOTP: true }); this.setState({ showTOTP: true });
setTimeout(() => {
if (this.codeInput && this.codeInput.focus) {
this.codeInput.focus();
}
}, 300);
return; return;
} }
Alert.alert(I18n.t('Oops'), I18n.t('Login_error')); Alert.alert(I18n.t('Oops'), I18n.t('Login_error'));
@ -138,12 +127,6 @@ class LoginView extends React.Component {
return false; return false;
} }
componentWillUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
}
setTitle = (title) => { setTitle = (title) => {
const { navigation } = this.props; const { navigation } = this.props;
navigation.setParams({ title }); navigation.setParams({ title });
@ -189,6 +172,7 @@ class LoginView extends React.Component {
<Text style={[sharedStyles.loginSubtitle, sharedStyles.textRegular]}>{I18n.t('Whats_your_2fa')}</Text> <Text style={[sharedStyles.loginSubtitle, sharedStyles.textRegular]}>{I18n.t('Whats_your_2fa')}</Text>
<TextInput <TextInput
inputRef={ref => this.codeInput = ref} inputRef={ref => this.codeInput = ref}
autoFocus
onChangeText={value => this.setState({ code: value })} onChangeText={value => this.setState({ code: value })}
keyboardType='numeric' keyboardType='numeric'
returnKeyType='send' returnKeyType='send'
@ -217,7 +201,7 @@ class LoginView extends React.Component {
<SafeAreaView style={sharedStyles.container} testID='login-view' forceInset={{ vertical: 'never' }}> <SafeAreaView style={sharedStyles.container} testID='login-view' forceInset={{ vertical: 'never' }}>
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold]}>{I18n.t('Login')}</Text> <Text style={[sharedStyles.loginTitle, sharedStyles.textBold]}>{I18n.t('Login')}</Text>
<TextInput <TextInput
inputRef={(e) => { this.usernameInput = e; }} autoFocus
placeholder={Accounts_EmailOrUsernamePlaceholder || I18n.t('Username_or_email')} placeholder={Accounts_EmailOrUsernamePlaceholder || I18n.t('Username_or_email')}
keyboardType='email-address' keyboardType='email-address'
returnKeyType='next' returnKeyType='next'

View File

@ -58,20 +58,20 @@ class NewServerView extends React.Component {
connectServer: PropTypes.func.isRequired connectServer: PropTypes.func.isRequired
} }
state = { constructor(props) {
text: '' super(props);
const server = props.navigation.getParam('server');
this.state = {
text: server || '',
autoFocus: !server
};
} }
componentDidMount() { componentDidMount() {
const { navigation, connectServer } = this.props; const { text } = this.state;
const server = navigation.getParam('server'); const { connectServer } = this.props;
if (server) { if (text) {
connectServer(server); connectServer(text);
this.setState({ text: server });
} else {
this.timeout = setTimeout(() => {
this.input.focus();
}, 600);
} }
} }
@ -87,12 +87,6 @@ class NewServerView extends React.Component {
return false; return false;
} }
componentWillUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
}
onChangeText = (text) => { onChangeText = (text) => {
this.setState({ text }); this.setState({ text });
} }
@ -150,7 +144,7 @@ class NewServerView extends React.Component {
render() { render() {
const { connecting } = this.props; const { connecting } = this.props;
const { text } = this.state; const { text, autoFocus } = this.state;
return ( return (
<KeyboardView <KeyboardView
contentContainerStyle={sharedStyles.container} contentContainerStyle={sharedStyles.container}
@ -163,7 +157,7 @@ class NewServerView extends React.Component {
<Image style={styles.image} source={{ uri: 'new_server' }} /> <Image style={styles.image} source={{ uri: 'new_server' }} />
<Text style={styles.title}>{I18n.t('Sign_in_your_server')}</Text> <Text style={styles.title}>{I18n.t('Sign_in_your_server')}</Text>
<TextInput <TextInput
inputRef={e => this.input = e} autoFocus={autoFocus}
containerStyle={styles.inputContainer} containerStyle={styles.inputContainer}
placeholder={defaultServer} placeholder={defaultServer}
value={text} value={text}
@ -177,7 +171,7 @@ class NewServerView extends React.Component {
title={I18n.t('Connect')} title={I18n.t('Connect')}
type='primary' type='primary'
onPress={this.submit} onPress={this.submit}
disabled={text.length === 0} disabled={!text}
loading={connecting} loading={connecting}
testID='new-server-view-button' testID='new-server-view-button'
/> />

View File

@ -65,12 +65,6 @@ class RegisterView extends React.Component {
}; };
} }
componentDidMount() {
this.timeout = setTimeout(() => {
this.nameInput.focus();
}, 600);
}
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState) {
const { customFields } = this.state; const { customFields } = this.state;
if (!equal(nextState.customFields, customFields)) { if (!equal(nextState.customFields, customFields)) {
@ -87,12 +81,6 @@ class RegisterView extends React.Component {
} }
} }
componentWillUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
}
setTitle = (title) => { setTitle = (title) => {
const { navigation } = this.props; const { navigation } = this.props;
navigation.setParams({ title }); navigation.setParams({ title });
@ -201,7 +189,7 @@ class RegisterView extends React.Component {
<SafeAreaView style={sharedStyles.container} testID='register-view' forceInset={{ vertical: 'never' }}> <SafeAreaView style={sharedStyles.container} testID='register-view' forceInset={{ vertical: 'never' }}>
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold]}>{I18n.t('Sign_Up')}</Text> <Text style={[sharedStyles.loginTitle, sharedStyles.textBold]}>{I18n.t('Sign_Up')}</Text>
<TextInput <TextInput
inputRef={(e) => { this.nameInput = e; }} autoFocus
placeholder={I18n.t('Name')} placeholder={I18n.t('Name')}
returnKeyType='next' returnKeyType='next'
iconLeft='user' iconLeft='user'

View File

@ -43,13 +43,13 @@ const styles = StyleSheet.create({
}); });
const Header = React.memo(({ const Header = React.memo(({
connecting, isFetching, serverName, showServerDropdown, setSearchInputRef, showSearchHeader, onSearchChangeText, onPress connecting, isFetching, serverName, showServerDropdown, showSearchHeader, onSearchChangeText, onPress
}) => { }) => {
if (showSearchHeader) { if (showSearchHeader) {
return ( return (
<View style={styles.container}> <View style={styles.container}>
<TextInput <TextInput
ref={setSearchInputRef} autoFocus
style={styles.server} style={styles.server}
placeholder='Search' placeholder='Search'
placeholderTextColor='rgba(255, 255, 255, 0.5)' placeholderTextColor='rgba(255, 255, 255, 0.5)'
@ -81,7 +81,6 @@ Header.propTypes = {
showSearchHeader: PropTypes.bool.isRequired, showSearchHeader: PropTypes.bool.isRequired,
onPress: PropTypes.func.isRequired, onPress: PropTypes.func.isRequired,
onSearchChangeText: PropTypes.func.isRequired, onSearchChangeText: PropTypes.func.isRequired,
setSearchInputRef: PropTypes.func.isRequired,
connecting: PropTypes.bool, connecting: PropTypes.bool,
isFetching: PropTypes.bool, isFetching: PropTypes.bool,
serverName: PropTypes.string serverName: PropTypes.string

View File

@ -21,15 +21,6 @@ class RoomsListHeaderView extends PureComponent {
setSearch: PropTypes.func setSearch: PropTypes.func
} }
componentDidUpdate(prevProps) {
const { showSearchHeader } = this.props;
if (showSearchHeader && prevProps.showSearchHeader !== showSearchHeader) {
setTimeout(() => {
this.searchInputRef.focus();
}, 300);
}
}
onSearchChangeText = (text) => { onSearchChangeText = (text) => {
const { setSearch } = this.props; const { setSearch } = this.props;
setSearch(text.trim()); setSearch(text.trim());
@ -51,10 +42,6 @@ class RoomsListHeaderView extends PureComponent {
} }
} }
setSearchInputRef = (ref) => {
this.searchInputRef = ref;
}
render() { render() {
const { const {
serverName, showServerDropdown, showSearchHeader, connecting, isFetching serverName, showServerDropdown, showSearchHeader, connecting, isFetching
@ -67,7 +54,6 @@ class RoomsListHeaderView extends PureComponent {
showSearchHeader={showSearchHeader} showSearchHeader={showSearchHeader}
connecting={connecting} connecting={connecting}
isFetching={isFetching} isFetching={isFetching}
setSearchInputRef={this.setSearchInputRef}
onPress={this.onPress} onPress={this.onPress}
onSearchChangeText={text => this.onSearchChangeText(text)} onSearchChangeText={text => this.onSearchChangeText(text)}
/> />

View File

@ -38,10 +38,6 @@ class SearchMessagesView extends React.Component {
this.rid = props.navigation.getParam('rid'); this.rid = props.navigation.getParam('rid');
} }
componentDidMount() {
this.name.focus();
}
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState) {
const { loading, searchText, messages } = this.state; const { loading, searchText, messages } = this.state;
if (nextState.loading !== loading) { if (nextState.loading !== loading) {
@ -128,7 +124,7 @@ class SearchMessagesView extends React.Component {
<StatusBar /> <StatusBar />
<View style={styles.searchContainer}> <View style={styles.searchContainer}>
<RCTextInput <RCTextInput
inputRef={(e) => { this.name = e; }} autoFocus
label={I18n.t('Search')} label={I18n.t('Search')}
onChangeText={this.search} onChangeText={this.search}
placeholder={I18n.t('Search_Messages')} placeholder={I18n.t('Search_Messages')}

View File

@ -53,9 +53,6 @@ class SetUsernameView extends React.Component {
} }
async componentDidMount() { async componentDidMount() {
this.timeout = setTimeout(() => {
this.usernameInput.focus();
}, 600);
const suggestion = await RocketChat.getUsernameSuggestion(); const suggestion = await RocketChat.getUsernameSuggestion();
if (suggestion.success) { if (suggestion.success) {
this.setState({ username: suggestion.result }); this.setState({ username: suggestion.result });
@ -73,12 +70,6 @@ class SetUsernameView extends React.Component {
return false; return false;
} }
componentWillUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
}
submit = async() => { submit = async() => {
const { username } = this.state; const { username } = this.state;
const { loginRequest, token } = this.props; const { loginRequest, token } = this.props;
@ -107,7 +98,7 @@ class SetUsernameView extends React.Component {
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold, styles.loginTitle]}>{I18n.t('Username')}</Text> <Text style={[sharedStyles.loginTitle, sharedStyles.textBold, styles.loginTitle]}>{I18n.t('Username')}</Text>
<Text style={[sharedStyles.loginSubtitle, sharedStyles.textRegular]}>{I18n.t('Set_username_subtitle')}</Text> <Text style={[sharedStyles.loginSubtitle, sharedStyles.textRegular]}>{I18n.t('Set_username_subtitle')}</Text>
<TextInput <TextInput
inputRef={e => this.usernameInput = e} autoFocus
placeholder={I18n.t('Username')} placeholder={I18n.t('Username')}
returnKeyType='send' returnKeyType='send'
iconLeft='at' iconLeft='at'