Для контекста я делаю динамическую c форму, в которой пользователь создает свои вопросы и тип каждого вопроса, например, простой текстовый ввод или даже ввод изображения. Список вопросов собран из локальной базы данных SQLite и используется для данных FlatList. Чтобы ответить на вопрос об изображении, я использую модал из модуляact-native-modal. Дело в том, что при показе мод я теряю состояние всех остальных полей, теряя все предыдущие ответы.
Вот мой код элемента: кстати, не обращайте внимания на теги, я использую стилевые компоненты для большей части стиля, а некоторые имена переменных на португальском языке, так что продолжайте это в виду. Камера является модулем реагирования на встроенную камеру.
function Item({ info, index }) {
const [resp, setResp] = useState(
DATA[index].resposta ? DATA[index].resposta : '',
);
// controla as respostas de cada pergunta
useEffect(() => {
dados[index] = {
nome_pergunta: info.nome ? info.nome : info.nome_pergunta,
resposta: resp,
id_pergunta: info.id_pergunta,
id_resposta: info.id_resposta ? info.id_resposta : null,
};
}, [resp]);
// caso o input seja do tipo texto
if (info.tipo === 'text') {
return (
<BlocoText>
<Label>{info.nome}</Label>
<Input
//placeholder={info.nome}
placeholderTextColor="white"
value={resp}
onChangeText={value => {
setResp(value);
}}
/>
</BlocoText>
);
}
// caso o input seja do tipo numero
else if (info.tipo === 'number') {
return (
<BlocoText>
<Label>{info.nome}</Label>
<Input
//placeholder={info.nome}
//placeholderTextColor="white"
value={resp}
onChangeText={value => {
setResp(value);
}}
keyboardType="decimal-pad"
/>
</BlocoText>
);
}
// caso o input seja do tipo multipla escolha
else if (info.tipo === 'select') {
const op = info.opcoes.split(',');
let items = [];
op.forEach(element => {
items.push({
color: '#000',
key: element.trim(),
value: element.trim(),
label: element.trim(),
});
});
return (
<BlocoText>
<Label>{info.nome}</Label>
<BlocoText4>
<Caixa>
<RNPickerSelect
value={resp}
onValueChange={value => setResp(value)}
placeholderTextColor="#000"
placeholder={placeholder}
useNativeAndroidPickerStyle={true}
items={items}
/>
</Caixa>
</BlocoText4>
</BlocoText>
);
}
// caso o input seja do tipo file
else if (info.tipo === 'file') {
return (
<BlocoImagem>
<BotaoImagem
onPress={() => {
setOption(index);
setModalVisible(true);
}}>
<Tela2>
<Label2>{info.nome}</Label2>
</Tela2>
<Tela2>
<Icon
name="camera"
size={25}
color="#FFF"
styles={{ marginLeft: 50 }}
/>
</Tela2>
</BotaoImagem>
<EnvolveImagem>
<ImagemCampoNovo
source={{
uri: resp
? 'data:image/png;base64,' + resp
: 'data:image/png;base64,' + Foto,
}}
/>
</EnvolveImagem>
</BlocoImagem>
);
}
// caso o input seja do tipo data
else if (info.tipo === 'date') {
return (
<BlocoText>
<Label>{info.nome}</Label>
<DatePicker
style={{ width: 295, marginLeft: 9 }}
date={resp}
mode="date"
placeholder="Selecione Uma Data"
format="DD-MM-YYYY"
confirmBtnText="Confirm"
cancelBtnText="Cancel"
customStyles={{
dateIcon: {
position: 'absolute',
left: 0,
top: 4,
marginLeft: 0,
},
dateInput: {
marginLeft: 36,
},
// ... You can check the source to find the other keys.
}}
onDateChange={date => {
setResp(date);
}}
/>
<Ajusta2 />
</BlocoText>
);
}
}
А вот код моей модальной камеры:
<Modal
transparent={false}
isVisible={modalVisible}
style={{ margin: 0 }}
onBackButtonPress={() => {
setModalVisible(false);
}}>
<View
style={{
alignSelf: 'center',
backgroundColor: '#015',
alignContent: 'center',
}}>
<RNCamera
ref={ref => setCamera(ref)}
style={{ flex: 1 }}
type={RNCamera.Constants.Type.back}
autoFocus={RNCamera.Constants.AutoFocus.on}
flashMode={RNCamera.Constants.FlashMode.off}
androidCameraPermissionOptions={{
title: 'Permissão para usar a câmera',
message: 'Precisamos da sua permissão para usar a câmera.',
buttonPositive: 'Ok',
buttonNegative: 'Cancelar',
}}
captureAudio={false}>
<View style={{ flex: 5 }} />
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={takePicture} style={styles.capture}>
<Icon name="camera" size={25} color="#7030a0" />
</TouchableOpacity>
</View>
</RNCamera>
</View>
</Modal>
Наконец, код the FlatList:
<Lista
windowSize={6}
data={DATA}
renderItem={({ item }) => (
<Item info={item} index={DATA.indexOf(item)} />
)}
keyExtractor={item => '' + DATA.indexOf(item)}
/>
Я пытался использовать другие методы рендеринга, например, использовать простую функцию array.map для рендеринга элементов, которые не работали, а также пытался найти альтернативу flatlist, так как у меня есть форма на другой странице приложения, но в состоянии stati c, и модал работает, не теряя состояния, но не смог найти хорошее решение.
У меня есть теория, что это может иметь отношение к тому, как я отношусь к изменению входных данных. Может быть, из-за того, что useEffect находится внутри самого Предмета, но я не могу придумать лучшего решения для хранилища данных Dynami c для последующего сохранения.
Я открыт для предложений, даже если это означает, что я не использую FlatList.
* РЕДАКТИРОВАТЬ: Вот несколько закуску к проблеме = https://snack.expo.io/@suxgatov / 7e28c3
Я использую реагировать родной cli в проекте, поэтому некоторые вещи должны были быть удалены для того, чтобы это работало. Например, библиотека камеры не работала, но любой модал имеет такой же результат, поэтому это не меняет проблему.