代码之家  ›  专栏  ›  技术社区  ›  ewizard

反应本机-从父组件重新引发子组件

  •  1
  • ewizard  · 技术社区  · 6 年前

    我正在修改日历- https://github.com/wix/react-native-calendars 因此,当我按一天,背景和文字的颜色变化的一天。我了解到,要重新渲染组件,需要更新父组件的状态,因此我正在尝试:

    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);
        }}
    
    ....
    

    儿童.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

    更新

    日历是在一个模式,我没有任何处理程序更新它的状态,这可能是问题吗?

    我在文件里找到这个:

    !免责声明!确保markedDates参数是不可变的。如果你 更改markedDates对象内容,但不更改对它的引用 不会触发更改日历更新。

    这是什么意思?

    更新

    我试着用一些谷歌搜索来解释这意味着什么,这有什么意义吗 this.state.markedDays

                    const markedDays = this.state.markedDays;
    
                    var dateString = `'${day.year}-${day.month}-${day.day}'`;
    
                    var addDate = {
                      [dateString]: {
                        customStyles: {
                          container: {
                            backgroundColor: '#6de3dc',
                          },
                          text: {
                            color: 'white',
                            fontWeight: 'bold'
                          },
                        },
                      }
                    }
    
                    const markedDaysHolder = {
                      ...markedDays,
                      ...addDate
                    }
    
                    this.state.markedDays = markedDaysHolder;
    

    更新

    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 回复  |  直到 6 年前
        1
  •  2
  •   Haider Ali    6 年前

    我也有这个问题,这是你需要做的

    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,
        })
      }
    
        2
  •  2
  •   safakeskin    4 年前

    这是我试图做的事情的答案。我想通过按日期来选择和取消选择日期(取消选择是@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'});
        }
    
    ....