Agenda doesn't update even when new data are added. Only when the app is reloaded it updates.
Here is my code:
const CalendarScreen = () => {
const list = useSelector((state) => state.getTodo.list);
const [items, setItems] = useState({});
const loadItems = () => {
list.forEach((data) => {
const strTime = data.createdDate;
if (!items[strTime]) {
items[strTime] = [];
list.forEach((datalist) => {
items[strTime].push({
name: datalist.title,
});
});
}
});
const newItems = {};
Object.keys(items).forEach((key) => {
newItems[key] = items[key];
});
setItems(newItems);
};
const renderItem = (item) => {
return (
<View >
<Text>{item.name}</Text>
</View>
);
};
return (
<View style={flex: 1}>
<Agenda
items={items}
loadItemsForMonth={loadItems}
renderItem={renderItem}
pastScrollRange={1}
futureScrollRange={1}
/>
</View>
);
};
export { CalendarScreen };
Expectation: Just want the Agenda to update automatically when new data is added in the state instead of having to reload the app.
It looks like that refresh depends call of loadItemsForMonth.
Unfortunately I cannot see when Agenda call loadItemsForMonth
Related
The idea is to have a toggle switch that switches from To Watch and Watched bookings. When I update a movie in the To Watch list, I want it to rerender the FlatList without that booking because it's now in the Watched list. And so when I press the toggle to see the Watched list I would now see the booking there. Same for reverse.
I have to press the toggle twice to see the change. Even when I open the screen for the first time it shows all the movies without the filter - this is the main thing I'm having trouble with. How can I get around this? This is the code I have:
const WatchList = () => {
const uid = auth.currentUser.uid;
const docRef = doc(db, 'users', uid);
const [user, setUser] = useState({});
const [watched, setWatched] = useState(true);
const [text, setText] = useState('To watch');
const [filteredBookings, setFilteredBookings] = useState(bookings);
const bookingsRef = collection(db, "booking"); // imamo ref ka bazi
const [bookings, setBookings] = useState({});
useEffect(() => {
getUser();
getBookings();
},[])
const getUser = async () => {
const snap = await getDoc(docRef)
setUser({user, ...snap.data()})
}
const getBookings = async () =>{
const q = query(bookingsRef, where("users","array-contains",auth.currentUser.uid));
const unsubscribe = onSnapshot(q, (querySnapshot) => {
const a = [];
querySnapshot.forEach((doc) => {
a.push(doc.data());
});
setBookings(querySnapshot.docs);
});
}
const toggleSwitch = () =>{
if(!watched){
setFilteredBookings(bookings.filter(function(item){
return item.data().watched == true;
}))
setText('Watched');
} else {
setText('To watch');
setFilteredBookings(bookings.filter(function(item){
return item.data().watched == false;
}))
}
setWatched(previousState => !previousState);
}
const updateBooking = async(id) => {
try {
await setDoc(doc(db, 'booking', id), {
watched: true
}, {merge: true})
}
catch(e) {
console.log(e)
}
}
const updateBooking1 = async(id) => {
try {
await setDoc(doc(db, 'booking', id), {
watched: false
}, {merge: true})
}
catch(e) {
console.log(e)
}
}
const deleteBooking = async(id) => {
try {
await deleteDoc(doc(db, 'booking', id));
}
catch(e) {
console.log(e)
}
}
useEffect(() => {
const resultOfFiltering = bookings
setFilteredBookings(resultOfFiltering)
}, [bookings])
return (
<View>
<View>
<Text>{text}</Text>
<Switch
value = {watched}
/>
</View>
<FlatList
data = {filteredBookings}
extraData = {watched}
renderItem = {({item}) => (
<View>
<View>
<Text>{item.data().movie}</Text>
<Text>{item.data().day} - {item.data().showtime}</Text>
</View>
<View>
{item.data().watched == true ? (
<TouchableOpacity style = {styles.delete} onPress = {() => {updateBookings(item.id); setFilteredBookings();}}>
<Image source={require('../assets/watched.png')}/>
</TouchableOpacity>
) : (
<TouchableOpacity onPress = {() => {updateBookings1(item.id); setFilteredBookings();}}>
<Image source={require('../assets/towatch.png')}/>
</TouchableOpacity>)}
<TouchableOpacity onPress = {() => {deleteBooking(item.id); setFilteredBookings();}}>
<Image source={require('../assets/remove.png')}/>
</TouchableOpacity>
</View>
</View>
)}
/>
</View>
)
}
export default WatchList
It's not really working properly at the moment and I'm not sure what I'm doing wrong so I'm kind of stuck. If I could get some help, I'd really appreciate it. Thank you!
I have multiple component which has state change during its data collection from get api call, are called from a single component get re-render multiple times , Please help to avoid re-render when open this page
const MyData = () => {
const [data, setData] = useState("");
const [newData, setNewData] = useState("");
const getData = () => {
axios.get("url").then(async function (response) {
setData(response);
});
};
const getData2 = () => {
axios.get("url").then(async function (response) {
setNewData(response);
});
};
useEffect(() => {
getData();
getData2();
});
const NewData = () => {
return (
<View>
<Text>{data.name}</Text>
</View>
);
};
const RewData = () => {
return (
<View>
<Text>{newData.name}</Text>
</View>
);
};
return (
<View>
<NewData />
<RewData />
</View>
);
};
You provide no dependency array (undefined) to your useEffect. If the component's state changes, then the useEffect will be called again, which sets the state again, and so on.
You can provide an empty dependency array which will cause the useEffect to be called only once.
useEffect(() => {
getData();
getData2();
}, []);
Edit: In response to the comments. You can prevent the screens content from rendering until the data has been fetched as follows.
const MyData = () => {
const [data, setData] = useState();
const [newData, setNewData] = useState();
const getData = () => {
axios.get("url").then(async function (response) {
setData(response);
});
};
const getData2 = () => {
axios.get("url").then(async function (response) {
setNewData(response);
});
};
useEffect(() => {
getData();
getData2();
}, []);
if (!data || !newData) {
return null
}
const NewData = () => {
return (
<View>
<Text>{data.name}</Text>
</View>
);
};
const RewData = () => {
return (
<View>
<Text>{newData.name}</Text>
</View>
);
};
return (
<View>
<NewData />
<RewData />
</View>
);
};
i am using socket.io or getting live crypto prices . it gives new prices each 10second. i have applied search functionality to get live price. but on every 10 sec my serach function get reverted and go back to normal state .
my code is below
const Item = ({ name }) => {
return (
<View style={styles.item}>
<Text>{name}</Text>
</View>
);
};
const renderItem = ({ item }) => <Item name={item.name} />;
const App = () => {
// this.arrayholder = DATA;
const [loading, setloading] = useState(false);
const [data, setdata] = useState("");
const [dasta, setdsata] = useState(DATA);
const [error, seterror] = useState(null)
const [searchValue, setsearchValue] = useState("")
useEffect(() => {
// setLoading(true);
var yui = socket.on("chat", (data) => {
setdata(data)
});
// console.log(yui.data)
}, []);
searchFunction = (text) => {
const updatedData = data.filter((item) => {
const item_data = `${item.name.toUpperCase()})`;
const text_data = text.toUpperCase();
return item_data.indexOf(text_data) > -1;
});
setdata(updatedData)
setsearchValue(text)
};
return (
<View style={styles.container}>
<SearchBar
placeholder="Search Here..."
lightTheme
round
value={searchValue}
onChangeText={(text) => searchFunction(text)}
autoCorrect={false}
/>
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
</View>
);
}
can u help pls . like when i search bitcoin it shows me bitcoin but after 10 seconds and it shows all the coin name .
you can also see here promblem
To maintain a current search state persistent although new coins are added to the list
you should call the searchFunction with the searchValue
Like
searchFunction(searchValue)
after getting the latest coin list
As previous value is saved in searchValue it will filter again your list
Form mine understanding without testing your code I assume you are getting you new data in useEffect
var yui = socket.on("chat", (data) => {
setdata(data);
});
So here call
searchFunction(searchValue)
After
setdata(data);
Or Simply replace your useEffect with
useEffect(() => {
// setLoading(true);
var yui = socket.on("chat", (data) => {
setdata(data);
searchFunction(searchValue);
});
// console.log(yui.data)
}, []);
I don't get any errors. I use flatlist in the home page of my code without any errors but it doesn't render in the second page. It also doesn't display console.log inside renderItem.
const NamazTakibi = () => {
const [ayet, setAyet] = useState('');
const fetchAyet = async () => {
try {
const ayet = await axios.get('https://api.acikkuran.com/surah/6/verse/1?author=14');
setAyet(ayet)
} catch {
console.log("error");
}
}
useEffect(() => {
fetchAyet();
}, []);
const renderItem = ({item}) => {
return (
<Cards item={item} />
)
}
return (
<FlatList
style={styles.container}
data={ayet}
renderItem={renderItem}
/>
)
};
export default NamazTakibi;
I have a flatlist that receives eventIds as data. On each renderItem call I want to find the corresponding event-object to each eventId on firebase and render this data. (E.g. title or image from this event)
This is the function to get a single event from firestore based on the eventId:
export async function getSingleEventDataFireStore(eventId) {
const db = firebase.firestore();
const eventFirestoreDoc = db.collection("events").doc(eventId);
const doc = await eventFirestoreDoc.get();
if (!doc.exists) {
console.log("No such Event!");
} else {
console.log("Event data fetched!");
return await doc.data();
}
}
this is where the flatlist is displayed:
const EventScreen = () => {
const [event, setEvent] = useState([]);
const [eventFetched, setEventFetched] = useState(false);
const eventIds = [{id:'1', eventId: 'jaelfmk130'}, {id:'2', eventId: '1jlk335n1'}]
const renderItem = ({ item }) => {
if (!eventFetched) {
firestore.getSingleEventDataFireStore(item.eventId).then((eventItem) => {
setEvent(eventItem);
setEventFetched(true);
});
}
setEventFetched(false)
return ( <View><Text>{event.title}</Text></View> )
}
return (
<View>
<FlatList
data={eventIds}
keyExtractor={(item) => item.id}
renderItem={renderItem}
/>
</View> )
}
This ends up in an infinite loop, because I set eventFetched to false again during renderItem. Otherwise, if I remove setEventFetched(false) it only renders one item.
How can I set eventFetched to false after the render of each item without ending up in a loop?