Я создаю приложение для отслеживания событий, использующее React-Native, Redux, React-Navigation и Expo, и у меня проблемы с довольно тривиальной частью.
У меня есть экран формы, где вы вводите имя события, дату и другую информацию. Я использую <TextInput/>
для ввода имени события, но не будет иметь значение onChange
, только onChangeText
. Кроме того, когда я использую событие onChange
, кнопка " Назад" в навигации становится неактуальной, и курсор остается только в TextInput независимо от того, где я нажимаю
У меня возникает другая проблема, связанная с памятью, которая заставляет симулятор загружаться дольше и дольше после каждой последовательной сборки и перестает отвечать после нескольких нагрузок. Иногда мое мобильное приложение-экспонат также вылетает из строя. У меня есть несколько смутное чувство, что эти два вопроса связаны, но я полностью потерял то, что может быть проблемой. В основном имитатор Exponent удваивает использование памяти каждый раз, когда я сохраняю файл.
Вот как выглядит CreateEventScreen.js
на данный момент, я собираюсь преобразовать его в Redux, как только я разрешу проблему onChange.
export default class CreateEvent extends Component {
constructor(){
super();
this.state = {
name: '',
date: new Date(),
repeatAnnually: false,
showDatePicker: false,
wallPaperSource: null
};
this.toggleSelectWallPaper = this._toggleSelectWallPaper.bind(this);
this.handleChange=this._handleChange.bind(this);
}
static navigationOptions = {
title: 'Create New Event'
}
_handleToggleSwitch = () => this.setState(state => ({
repeatAnnually: !this.state.repeatAnnually
}));
/* THIS IS NOT WORKING */
_handleChange = (event) => {
console.log(event);
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
})
}
_onDateChange = (date) => this.setState(state => ({
date: date
}));
_toggleSelectWallPaper = async() => {
let result;
try {
result = await ImagePicker.launchImageLibraryAsync({
allowEditing: true,
aspect: [4, 3]
});
} catch (e) {
result = null;
}
if(!result.cancelled){
this.setState({
wallPaperSource: result.uri
});
}
}
_renderDatePicker(){
if(this.props.showDatePicker){
return (
<DatePickerIOS
date={this.state.date}
mode="date"
onDateChange={this._onDateChange}
/>
)
} else {
return null;
}
}
render(){
const { onClick, toggleDatePicker, showDatePicker } = this.props
let { wallPaperSource } = this.state;
return(
<View>
<TextInput
style={styles.input}
name="name"
placeholder="Event Name"
value={this.state.name}
/* THIS IS NOT WORKING */
onChange={this._handleChange}
/* This works but not ideal for redux integration */
// onChange={(event) => this.setState({'name': event.target.value})}
/>
<View style={styles.eventDetailsContainer}>
<View style={styles.itemContainer}>
<Text>Repeat Annually</Text>
<Switch
onValueChange={this._handleToggleSwitch}
value={this.state.repeatAnnually}
/>
</View>
<TouchableOpacity onPress={e => {
e.preventDefault()
toggleDatePicker(showDatePicker)
}}>
<View style={styles.itemContainer}>
<Text>Select Date</Text>
<Text>{this.state.date.toLocaleDateString()}</Text>
</View>
</TouchableOpacity>
<View>
{this._renderDatePicker()}
</View>
</View>
<View style={styles.eventDetailsContainer}>
<TouchableOpacity onPress={this.toggleSelectWallPaper}>
<View style={styles.itemContainer}>
<Text>Wallpaper</Text>
{ this.state.wallPaperSource ?
<Image source={{ uri: wallPaperSource }} style={{ width: 100, height: 100 }}/>
: null
}
</View>
</TouchableOpacity>
</View>
<Button
style={styles.submitBtn}
onPress={e => {
e.preventDefault()
if(!this.state.name.trim()){
return
}
onClick(this.state)
}}
color="#1e90ff"
title="Create Event"
/>
</View>
)
}
}
package.json -
{
"name": "floss-evens",
"version": "0.0.0",
"description": "Hello Expo!",
"author": null,
"private": true,
"main": "node_modules/expo/AppEntry.js",
"dependencies": {
"expo": "^18.0.4",
"lodash": "^4.17.4",
"moment": "^2.18.1",
"prop-types": "^15.5.10",
"react": "16.0.0-alpha.12",
"react-native": "https://github.com/expo/react-native/archive/sdk-18.0.1.tar.gz",
"react-native-image-picker": "^0.26.3",
"react-navigation": "^1.0.0-beta.11",
"react-redux": "^5.0.5",
"redux": "^3.7.2"
}
}
Любая помощь или обратная связь были бы весьма признательны. Спасибо!
Объект события, onChange
в onChange
является большим и останавливает выполнение другого js, если он зарегистрирован. Просто удалите console.log(event);
,
При использовании onChange
входное значение может быть получено с помощью event.nativeEvent.text
. Однако вы не должны захватывать входные значения. Правильный подход - использовать onChangeText
.
TextInput
не имеет свойства с именем name, которое будет просто проигнорировано.
// This will not be defined
const name = target.name;
Вы можете указать дополнительные параметры для _handleChange
для выполнения предполагаемого действия:
onChangeText={(value) => this._handleChange(value, 'keyName')}
Если вы хотите обработать это автоматически, например, для большого количества входов, см. Этот вопрос.
onChangeText
? Просто предположение, но объект события может быть огромным, и простое ведение журнала может остановить выполнение других js. Если вы удалитеconsole.log
, решит ли это проблему отсутствия ответа?OnChangeText
не использоватьOnChangeText
том, что он не очень многократно используется в том смысле, что мне придется вручную устанавливать обновляемый ключ. Кроме того, я думаю, что будет сложнее, если я добавлю в него избыточность этого компонента. Вы были правы относительно удаленияconsole.log
! Спасибо тебе за это. СобытиеonChange
работает. Однако теперь я регистрирую целевойconsole.log('target', event.target)
и все, что он мне дает, это "47" для любого ввода.