S
S
Sneiksus2022-03-30 23:33:53
JavaScript
Sneiksus, 2022-03-30 23:33:53

How to synchronize the state in two different components?

When you swipe the list of pairs in the lesson list component, the state index changes. Also, in the dataslider component, when you click on the number of the day, the state with the index also changes. You need to synchronize the states so that when the state changes in the data slider, the state changes in the lesson list and vice versa. Preferably without using redux.

Lesson list

import React, { useState, useEffect, useRef, useMemo, useContext } from 'react';
import { StyleSheet, Text, View, FlatList, Dimensions, ScrollView } from 'react-native'
import AntDesign from '@expo/vector-icons/AntDesign';

const { width } = Dimensions.get('screen');

const LessonList = ({ data, index, setIndex }) => {
  //const index = useContext(IndexContext);
  const lessonsRef = React.useRef<FlatList>()

  return (
    <FlatList
      ref={lessonsRef}
      initialNumToRender={3}
      initialScrollIndex={index}
      data={data.days}
      maxToRenderPerBatch={3}
      keyExtractor={(item) => item.date}
      getItemLayout={(data, index) => (
        {length: width, offset: width * index, index}
      )}
      onMomentumScrollEnd={ev => {
        setIndex(Math.floor(ev.nativeEvent.contentOffset.x / width))
      }}
      horizontal
      pagingEnabled
      showsHorizontalScrollIndicator={false}
      renderItem={({ item, index: fIndex }) => {
        return (
          <ScrollView
            showsVerticalScrollIndicator={false}
            contentContainerStyle={styles.lessons_scrollview}>
            {item.lessons.map((item) => (
              <Lesson key={item.id} item={item} />
            ))}
          </ScrollView>
        );
      }}
    />
  );
}

const Lesson = ({ item }) => {
  return (
    <View style={styles.lessons}>
      <View style={styles.lesson_time}>
        <Text style={styles.lesson_time_list_text}>{item.starttime}</Text>
        <Text style={styles.lesson_time_end_list_text}>{item.endtime}</Text>
      </View>
      <View style={styles.lesson_card}>
        <Text style={styles.lesson_card_name}>{item.name}</Text>
        <Text style={styles.lesson_card_description}>{item.description}</Text>
        <Text style={styles.lesson_card_locate}>
          <AntDesign name="enviromento" size={16} color="white" />
          {item.location}
        </Text>
        <Text style={styles.lesson_card_teacher}>
          <AntDesign name="user" size={16} color="white" />
          {item.teacher}
        </Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  lessons_scrollview: {
    paddingHorizontal: 15,
    width: width,
    paddingTop: 15,
  },
  lessons: {
    flexDirection: "row",
  },
  lesson_time_text: {
    fontFamily: "eUkraineBold",
    fontSize: 9,
    paddingRight: 30,
    color: "#BCC1CD",
  },
  lesson_time: {
    flexDirection: "column",
    paddingRight: 9,
    borderRightWidth: 1,
    borderRightColor: "#FAF9F9",
  },
  lessons_text: {
    fontFamily: "eUkraineBold",
    fontSize: 9,
    color: "#BCC1CD",
  },
  lesson_time_list: {
    flexDirection: "column",
    paddingTop: 14,
  },
  lesson_time_list_text: {
    fontFamily: "eUkraineMedium",
    fontSize: 14,
  },
  lesson_time_end_list_text: {
    fontFamily: "eUkraineMedium",
    fontSize: 14,
    color: "#BCC1CD",
  },
  lesson_card: {
    flexDirection: "column",
    marginLeft: 16,
    backgroundColor: "#4DC591",
    borderRadius: 16,
    paddingTop: 16,
    paddingLeft: 16,
    paddingBottom: 17,
    flex: 1,
    marginBottom: 16,
  },
  lesson_card_name: {
    fontFamily: "eUkraineBold",
    fontSize: 13,
    color: "#ffff",
  },
  lesson_card_description: {
    fontFamily: "eUkraineMedium",
    fontSize: 10,
    paddingTop: 4,
    color: "#ffff",
  },
  lesson_card_locate_img: {
    height: 16,
    width: 16,
    marginRight: 50,
    tintColor: "#FFFFFF",
  },
  lesson_card_locate: {
    fontFamily: "eUkraineRegular",
    fontSize: 10,
    paddingTop: 15,
    color: "#ffff",
  },
  lesson_card_teacher_img: {
    //marginRight: 500,
  },
  lesson_card_teacher: {
    fontFamily: "eUkraineRegular",
    fontSize: 10,
    paddingTop: 3,
    color: "#ffff",
  },
});

export default LessonList


data slider
import React, { useState, useEffect, useRef, useMemo } from 'react';
import { TouchableOpacity, FlatList, StyleSheet, Text, View, Dimensions } from 'react-native';
import Moment from 'react-moment';
import moment from 'moment';
import 'moment/locale/uk';

const { width } = Dimensions.get('screen');

const DateSlider = ({ data, index, setIndex }) => {
  const _spacing = 11;
  const _colors = {
      active: `#FF7648`,
      inactive: `#fff`,
  };
  const [startday, setstartday] = useState(updatestartday());
  const ref = useRef<FlatList>(null);

  useEffect(() => {
    const interval = setInterval(() => setstartday(updatestartday()), 60000);
    return () => clearInterval(interval);
  }, []);

  function updatestartday() {
    console.log('Update Start Week Day');
    return moment().subtract(1, 'week').startOf('week');
  }

  const generatedayslist = useMemo(() => {
    let date = []
    let day = startday.clone()
    let i = 0;

    while (i++ < 21){
      date.push(day.clone())
      day.add(1, 'day')
    }
    
    return date
  }, [startday])

  //const [index, setIndex] = useState(setindexday());

  function setindexday() {
    let i = 0;

    while (i++ < 21){
      if (moment(generatedayslist[i]).date() == moment().date())
        break;
    }
    
    return i
  }

  useEffect(() => {
    ref.current?.scrollToIndex({
      index: index,
      animated: true,
      viewPosition: 0,
      viewOffset: _spacing
    })
  }, [index])
  
  return (
    <FlatList
    ref={ref}
    initialNumToRender={8}
    initialScrollIndex={index}
    getItemLayout={(data, index) => (
      {length: 54.5, offset: 54.5 * index, index}
    )}
    data={generatedayslist}
    keyExtractor={(item) => item}
    contentContainerStyle={{ paddingLeft: _spacing, paddingBottom: 25 }}
    showsHorizontalScrollIndicator={false}
    horizontal
    renderItem={({ item, index: fIndex }) => {
      return (
        <TouchableOpacity onPress={() => { setIndex(fIndex) }}>
          <View
            style={{
              marginRight: _spacing,
              borderRadius: 10,
              backgroundColor: 
              fIndex == index ? _colors.active : _colors.inactive,
              width: 43
            }}>
            <Moment element={Text} style={fIndex == index ? styles.day_flatlist_select 
              : styles.day_flatlist} format='dd'>{item}</Moment>
            <Moment element={Text} style={fIndex == index ? styles.day_flatlist_select 
              : styles.day_flatlist} format='D'>{item}</Moment>
          </View>
        </TouchableOpacity>
      );
    }}
  />
  );
}

const styles = StyleSheet.create({
  day_flatlist: {
    fontFamily: 'eUkraineBold',
    fontSize: 13, 
    textTransform: 'uppercase',
    textAlign: 'center',
    color: '#000',
  },
  day_flatlist_select: {
    fontFamily: 'eUkraineBold',
    fontSize: 13, 
    textTransform: 'uppercase',
    textAlign: 'center',
    color: '#FFF',
  },
});

export default DateSlider

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Shamanov, 2022-04-01
@SilenceOfWinter

via event or global reactive object

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question