React Native - переназначить дочерний компонент из родительского компонента - PullRequest
0 голосов
/ 21 сентября 2018

Я пытаюсь изменить календарь - https://github.com/wix/react-native-calendars, чтобы при нажатии на день цвета фона и текста менялись для этого дня.Я прочитал, что для повторного рендеринга компонента вам необходимо обновить состояние родительского компонента, вот что я пытаюсь:

Parent.js

export default class InitiateRent extends Component {
  state = {
    ....
    this.markedDays: {},
    someVar: 0
  };

  constructor() {
    super(); 
    this.handler = this.handler.bind(this);
    this.markedDays = {};
  }

  ....

  handler(e) {
    console.log('handler running');
    this.setState({
      someVar: 123
    })
  }

  <Calendar 
    handler={this.handler}
    markedDates={this.markedDays}
    onDayPress={(day)=> {
      console.log('selected day', day);

      var dateString = `'${day.year}-${day.month}-${day.day}'`

      var addDate = {
        [dateString]: {
          customStyles: {
            container: {
              backgroundColor: '#6de3dc',
            },
            text: {
              color: 'white',
              fontWeight: 'bold'
            },
          },
        }
      }

      this.markedDays = Object.assign(addDate, this.markedDays);

      console.log(this.markedDays);
    }}

....

Child.js

pressDay(date) {
    this.props.handler();
    this._handleDayInteraction(date, this.props.onDayPress);
}

renderDay(day, id) { //GETS CALLED IN CHILD RENDER METHOD VIA AN INTERMEDIARY
    ....
        <DayComp
          ....
          onPress={this.pressDay}
          ....
}

Все работает правильно, за исключением того, что я не получаю ожидаемый результат - когда я нажимаю дату в календаре, обработчик срабатывает, состояние меняется, и в консоли мой объект выглядит правильно:

Object

'2018-9-23': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}

'2018-9-26': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}

'2018-9-28': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}

'2018-9-29': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}

Но фон дня в календаре не меняется, равно как и текст - что мне нужно сделать, чтобы заставить его повторно отобразить (изменить)?

ОБНОВЛЕНИЕ

Я создал цепочку обработчиков от самого нижнего компонента day, который представляет всего один день в календаре вплоть до родительского представления высшего порядка (не App.JS, но чуть ниже), и это все еще ничего не сделал.

ОБНОВЛЕНИЕ

Календарь находится на модальном, и у меня нет никакого обработчика на это обновлениеэто состояние, может ли это быть проблемой?

ОБНОВЛЕНИЕ

Я нашел это в документах:

! Отказ от ответственности!Убедитесь, что значение параметра notesDates является неизменным.Если вы измените содержимое объекта markDates, но ссылка на него не изменится, обновление календаря не будет запущено.

Что это значит?

ОБНОВЛЕНИЕ

Я пытался истолковать, что это значит, с помощью некоторых поисков в Google, делает ли это this.state.markedDays неизменным?

componentDidUpdate(prevProps, prevState, snapshot) {
  console.log("componentDidUpdate in InitiateRent:", prevProps, prevState, snapshot);
}

Вывод выше:

componentDidUpdate in InitiateRent: (3) (index.bundle, line 761)

{initiateRentMessage: function, modalHeight: 200, modalWidth: 200, handler: function}

{modalVisible: true, message: "Hi, I would like to rent an item from you.", rentButtonBackground: "#6de3dc", someVar: 123, markedDays: Object}

undefined

Я вижу, как состояние объекта markedDays увеличивается с каждым нажатием кнопки из этого выхода, почему не стильизменение?

Во всех соответствующих компонентах, и я заметил, что он не срабатывает на компоненте самого низкого порядка, который нужно изменить.

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Это скрытый ответ за то, что я пытался сделать.Я хотел иметь возможность выбирать и отменять выбор даты, нажимая на нее (отмена выбора, являющаяся проблемой после того, как @HaiderAli помог):

Все, что мне нужно было сделать, это:

onDayPress = (day) => {
      const _selectedDay = day.dateString;

      let marked = true;
      if (this.state._markedDates[_selectedDay]) {
        // Already in marked dates, so reverse current marked state
        marked = !this.state._markedDates[_selectedDay].selected;
        console.log('marked:', marked);
      }

      // Create a new object using object property spread since it should be immutable
      // Reading: https://davidwalsh.name/merge-objects
      const updatedMarkedDates = {...this.state._markedDates, ...{ [_selectedDay]: { 'selected': marked, 
                                                                                      customStyles: {
                                                                                        container: {
                                                                                          backgroundColor: '#6de3dc',
                                                                                        },
                                                                                        text: {
                                                                                          color: 'white',
                                                                                          fontWeight: 'bold'
                                                                                        },
                                                                                      }, 
                                  } } }

      // Triggers component to render again, picking up the new state
      this.setState({ _markedDates: updatedMarkedDates });
}

Я добавил'selected':, который должен быть там, и эта функция улучшает ответ @ HaiderAli.

Чтобы отменить выбор для работы, откройте node_modules/react-native-calendars/src/calendar/day/custom/index.js (Это неправильный файл для вас, если вы не используете markingType={'custom'} опора в календаре. Если вы не используете опору, отредактируйте node_modules/react-native-calendars/src/calendar/day/basic/index.js).Сделайте это изменение:

....

render() {
    let containerStyle = [this.style.base];
    let textStyle = [this.style.text];

    let marking = this.props.marking || {};
    if (marking && marking.constructor === Array && marking.length) {
      marking = {
        marking: true
      };
    }
    const isDisabled = typeof marking.disabled !== 'undefined' ? marking.disabled : this.props.state === 'disabled';

    console.log('marking in day:', marking.selected);

    if (marking.selected) {
      containerStyle.push(this.style.selected);
    } else if (isDisabled) {
      textStyle.push(this.style.disabledText);
    } else if (this.props.state === 'today') {
      containerStyle.push(this.style.today);
      textStyle.push(this.style.todayText);

    /********ADD THIS CONDITION********/
    } else if(!marking.selected) { 
      textStyle.push({backgroundColor: '#ffffff', color: '#2d4150'});
    }

....
0 голосов
/ 22 сентября 2018

У меня тоже была эта проблема, вот что вам нужно сделать

constructor(props) {
    super(props)
    this.state = {
    }
    this.onDayPress = this.onDayPress
  }

showCalendar = () => {
    return (
      <Calendar
        onDayPress={this.onDayPress}
        style={styles.calendar}
        hideExtraDays
        markedDates={{
          [this.state.selected]: {
            selected: true,
            disableTouchEvent: true,
            selectedDotColor: 'orange',
          },
        }}
      />
    )
  }

onDayPress = day => {
    this.setState({
      selected: day.dateString,
    })
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...