#reactjs #react-native #react-native-android #scrollview #react-native-ios
#reactjs #react-native #react-native-android #scrollview #react-native-ios
Вопрос:
Я хочу прокрутить до вершины со ссылкой на идентификатор изначально для данного списка элементов, поэтому я пишу следующий код —
import React, {useState, useEffect, useRef} from 'react';
import {
SafeAreaView,
ScrollView,
TouchableOpacity,
ActivityIndicator,
} from 'react-native';
import axios from 'axios';
import NotExpandedVaccineComponent from '../../../../components/Home/NotExpandedVaccineComponent';
import ExpandedVaccineComponent from '../../../../components/Home/ExpandedVaccineComponent';
import {ROOT} from '../../../../services/ApiUrl';
export default function VaccinationListScreen(props) {
const {navigation} = props;
const [data, setData] = useState([]);
const [changedstatus, setChangedStatus] = useState(null);
const [loading, setisLoading] = useState(true);
const scrollRef = useRef(null);
let id = props.route.params.id;
let interbalIdArr;
const childdob = props.route.params?.childdob;
const selectedid = props.route.params?.selectedid;
const [expand, setExpand] = useState({});
let vaccinenameselected = props.route.params?.vaccineitem;
console.log('vaccine selected', vaccinenameselected);
const changevaccinestatus = (value) => {
setChangedStatus(value);
};
const handleClickOnYourElem = (y) =>
scrollRef.current.ScrollTo({y, animated: true});
const getData = () => {
let url = `${ROOT}/children/${id}/vaccinations`;
axios
.get(url)
.then(function (res) {
console.log(res);
setData(res.data.content);
setisLoading(false);
const items = res.data.content;
items.map((a) => {
const arr = a.vaccine_list.map((a) => a.vaccineInternalId);
console.log('arr', arr);
if (arr.includes(selectedid)) {
console.log('jj', a.id);
setExpand({[a.id]: true});
}
});
})
.catch(function (err) {
console.log(err);
});
};
useEffect(() => {
getData();
selectedid amp;amp; handleClickOnYourElem(selectedid);
}, [changedstatus, loading]);
function handleOnPress(id, item) {
setExpand((prev) => {
let toggleId = true;
if (prev[id]) {
toggleId = {[id]: false};
} else {
toggleId = {[id]: true};
}
return {...toggleId};
});
}
if (data == '' || loading == true) {
return (
<ActivityIndicator
color="#FF1493"
size="large"
style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}
/>
);
} else {
return (
<SafeAreaView>
<ScrollView horizontal pagingEnabled ref={scrollRef}>
{data != '' amp;amp;
data !== undefined amp;amp;
data !== null amp;amp;
data.map((item) => {
const selected = item.vaccine_list
.map((a) => a.vaccineInternalId)
.includes(selectedid);
return (
<TouchableOpacity
key={item.id}
style={{
paddingLeft: 10,
paddingRight: 10,
}}
onPress={() => handleOnPress(item.id, item)}>
{expand[item.id] ? (
<ExpandedVaccineComponent
item={item}
id={id}
navigation={navigation}
changevaccinestatus={changevaccinestatus}
childdob={childdob}
/>
) : (
<NotExpandedVaccineComponent item={item} />
)}
</TouchableOpacity>
);
})}
</ScrollView>
</SafeAreaView>
);
}
}
Но когда я выполняю то же самое, я получаю, что null не является объектом (вычисление ‘scrollRef.current.scrollTo’).
Почему это так? Не мог бы кто-нибудь указать, где я ошибся? Застрял с давних пор, пожалуйста, помогите мне. Любые выводы были бы замечательными, спасибо.
Ответ №1:
кажется , ты забываешь current
.
Вам нужно использовать его следующим образом:
...
const scrollRef = useRef();
const handleClickOnYourElem = y =>scrollRef.current.ScrollTo({y,animated: true});
return (
<ScrollView ref={scrollRef} >
...
И это не связано с вашим Q, а вместо
{data != '' amp;amp;
data !== undefined amp;amp;
data !== null amp;amp;
data.map((item) => {
Вы можете просто использовать: data?.map((item=> ...
И не нужно создавать дополнительный массив для проверки выбранного:
Вы можете заменить это:
const selected = item.vaccine_list
.map((a) => a.vaccineInternalId)
.includes(selectedid);
с помощью:
const selected = (item.vaccine_list.find(({vaccineInternalId})=>vaccineInternalId===selectedid))?.vaccineInternalId
Комментарии:
1. Я получаю null не является объектом (вычисление ‘scrollRef.current. scrollTo’)
2. попробуйте
const scrollRef = useRef();
и посмотрите, что произойдет3. все та же ошибка
4. удалите <SafeArea…> и проверьте
Ответ №2:
На основе отредактированного сообщения это должно быть изменено:
useEffect(() => {
getData();
selectedid amp;amp; handleClickOnYourElem(selectedid);
}, [changedstatus, loading, selectedid]); // need "selectedid" as dependency
// Ниже приведено старое содержимое, игнорировать
Попробуйте эти
const vaccineRef = useRef(null);
ref={vaccineRef}
React.useLayoutEffect(() => {
vaccineRef.current.scrollTo(selectedid);
}, [selectedid]);
Комментарии:
1. вы хотите, чтобы я добавил useLayoutEffect внутри useEffect?
2. Нет, я предлагал заменить несколько строк и добавить дополнительную
useLayoutEffect
. Извините за неясный ответ. Обновлено и надеюсь, что это поможет.3. где я должен использовать эффект useLayoutEffect? Нужно ли мне это?
4. Он выдает scrollViewRef.current.scrollTo не является функцией, почему это так?