@Sneiksus

Как синхронизировать стейт в двух разных компонентах?

При свайпе списка пар в компоненте lesson list меняется стейт индекс. Также в компоненте dataslider при нажатии на число дня тоже меняется стейт с индексом.Нужно синхронизировать стейты, чтобы при изменении стейта в data slider изменялся стейт и в lesson list и наоборот.Желательно без использования 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
  • Вопрос задан
  • 105 просмотров
Пригласить эксперта
Ответы на вопрос 1
SilenceOfWinter
@SilenceOfWinter
та еще зажигалка...
через событие или глобальный реактивный объект
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы