1

Let me summarize a lil bit, what I'm trying to do is when the news is clicked, a modal (in this case I used a library: react-native-modalize https://github.com/jeremybarbet/react-native-modalize) is presented with the respective details of the clicked news

In order for the content inside the modal to be dynamic, I used states to store the details, so whenever a click is registered on the news, a series of details is passed thru function parameters and store in the respective state

THE PROBLEM is that whenever a state on the top level is changed the whole component refresh itself, and it's causing problem like:

Scenario 1: when the user scroll until the end of the scroll view and pressed on one of the news, modal is brought up and because the state is being changed, the whole app refreshes and the scroll view jumps back to the top.

app.js

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { useRef, useState, useEffect } from 'react';
import { AppLoading } from 'expo'
import { StyleSheet, Text, View, FlatList, SafeAreaView, ScrollView, Image,  TouchableOpacity } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Modalize } from 'react-native-modalize';
import { Ionicons } from '@expo/vector-icons';
import { render } from 'react-dom';

import Header from './components/Header';
import NuaDaily from './components/Daily';
import Content from './components/Content';

import moment from "moment";

const HomeStackScreen = () => {

  const [title, setTitle] = useState([])
  const [author, setAuthor] = useState([])
  const [publication, setPublication] = useState([])
  const [imageUrl, setImageUrl] = useState([])
  const [summary, setSummary] = useState([])

  const modalizeRef = useRef(null);
  const onOpen = (title, author, publication, imageUrl, summary) => {
    modalizeRef.current?.open();
    setTitle(title)
    setAuthor(author)
    setPublication(publication)
    setImageUrl(imageUrl)
    setSummary(summary)
  };

  return (
    <>

    <SafeAreaView style={styles.container}>
      <ScrollView style={styles.scrollView}>
        <View style={styles.container}>
          <Header />
          <NuaDaily modalize={onOpen} style={styles.nuadaily} />
          <Content modalize={onOpen} />
        </View>
      </ScrollView>
    </SafeAreaView>

    <Modalize snapPoint={650} modalTopOffset={10} ref={modalizeRef} style={{ width: '100%',   alignItems: 'center', justifyContent: 'center', padding: 20 }}>
      <View style={{padding: 20}}>
        <Image
          style={{width: 350, height: 200, zIndex: 1000, borderRadius: 8, marginTop: 10}}
          source={{ uri: `${imageUrl}` }}
        />
        <Text style={styles.modalTitle}>{title}</Text>

        <View style={styles.detailsBar}>
          <Text style={styles.modalAuthor}>{author}</Text>
          <Text style={styles.modalPublication}>{moment(publication).format("MM-DD-YYYY")}</Text>
        </View>

        <Text style={styles.modalSummary}>{summary}</Text>
      </View>
    </Modalize>
    </>
  )
}

const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator
        tabBarOptions={
          {
            activeTintColor: '#00B2FF',
            inactiveTintColor: 'gray',
            showLabel: false,
            style: { height: 60, borderRadius: 0, backgroundColor: 'rgba(255, 255, 255, 0.85)'}
          }
        }
        showLabel = {false}
        screenOptions={({ route }) => ({
          tabBarIcon: ({ focused, color, size }) => {
            if (route.name === 'Home') {
              return <HomeIcon />
            }
          },
        })}
      >
        <Tab.Screen name="Home"
          component={
          HomeStackScreen
        } />
      </Tab.Navigator>
    </NavigationContainer>
  );
}
});

Daily (index.js) (imported on app.js)

import React from 'react';
import { useState, useEffect } from 'react';
import {View, Text, FlatList, Image, ImageBackground, ScrollView, SafeAreaView, TouchableOpacity} from 'react-native';
import axios from 'axios';
import moment from "moment";
import * as Font from 'expo-font';
import AppLoading from 'expo-app-loading';
import { useFonts } from 'expo-font';
import styles from './style';
import Dot from '../../assets/images/dot.svg';

const nuaDaily = ( props ) => {

    const Item = ({ title, author, publication, imageUrl, summary }) => (
        
        <View style={styles.item}>
            <TouchableOpacity onPress={()=>props.modalize(title, author, publication, imageUrl, summary)}>
                <Image
                    style={{width: 210, height: 200, zIndex: 1000, borderRadius: 8, marginTop: 10}}
                    source={{ uri: `${imageUrl}` }}
                />
                <Text style={ [styles.title, {fontFamily: 'Poppins'}]}>{title}</Text>
                <View style={styles.bottomBar}>
                    <Text style={styles.author}>{author}</Text>
                    <Text style={styles.publication}>{moment(publication).format("MM-DD-YYYY hh:mm")}</Text>
                </View>
            </TouchableOpacity>
        </View>
        
    );

    const renderItem = ({ item }) => {

        if(moment(item.publication).isSame(moment(), 'day')){
            return <Item title={item.title} author={item.newsSite} publication={item.publishedAt} imageUrl={item.imageUrl} summary={item.summary} />
        }else{
            // return <Item title={item.title} author={item.newsSite} publication={item.publishedAt} imageUrl={item.imageUrl} summary={item.summary} />
        }
        
    };

    const [data, setData] = useState([])

    useEffect(() => {

        axios.get(APIURL)
        .then((res) => {
            setData(res.data)
        })
        .catch((err) => {
            console.log(`error calling API ${err}`)
        })

    },[])
        return (
            <View style={styles.container}>
                <View style={styles.containerTitle}>
                    <Dot style={styles.dot} />
                    <Text style={ [styles.PrimaryText , {fontFamily: 'Quicksand'}]}>NUA Daily</Text>
                </View>
                <FlatList
                    showsHorizontalScrollIndicator={false}
                    horizontal={true}
                    data={data}
                    renderItem={renderItem}
                    style={styles.flatList}
                />
            </View>
        )
}

export default nuaDaily;

Demo of the problem (Scenario 1)

Shaun Mak
  • 11
  • 1
  • 2
  • You can store scrollbar position in a state variable. You may have a look - https://stackoverflow.com/a/59101106/6426569 – MukulSharma Apr 06 '21 at 14:55

0 Answers0