使用按钮更改祖父母组件中的状态

时间:2020-06-02 12:10:51

标签: javascript reactjs components parent-child setstate

您好,我是React的新手,必须做一个Tutorial,在其中必须使用按钮onClick函数更改Child Component的状态。 目前,我在父组件中使用一个按钮来完成此操作,但现在我必须在其他子组件中使用此按钮,而不是直接在父组件中使用此按钮来重新启动我的教程。

但是我不知道该怎么做。 对每个建议都不满意。

class Child extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      run: this.props.run,
      stepIndex: this.props.stepIndex
    }
  }


 componentWillReceiveProps (props) {
    this.setState({ run: props.run, stepIndex: props.stepIndex })
  }

callback = (tour) => {
    const { action, index, type } = tour

    // if you delete  action === 'skip', the Tutorial will not start on other pages after skipped once.
    if (action === 'close' || action === 'skip' || type === 'tour:end') {
      this.setState({ run: false })
    } else if ([EVENTS.STEP_AFTER, EVENTS.TARGET_NOT_FOUND].includes(type)) {
      this.setState({ stepIndex: index + (action === ACTIONS.PREV ? -1 : 1) })
    }
  }

 render () {
    let { run, stepIndex, steps } = this.state

    if (this.props.location.pathname === '/') {
      steps = []
      run = false
    } else if (this.props.location.pathname === '/matches/' || this.props.location.pathname.length === '/matches') {
      steps = matchSiteSteps
    } else if (this.props.location.pathname.startsWith('/matches/') && this.props.location.pathname.endsWith('/edit/')) {
      steps = matchEditorSteps
    } else if (this.props.location.pathname.startsWith('/matches/') && this.props.location.pathname.includes('sequence')) {
      steps = matchSequenceSteps
    } else if (this.props.location.pathname.startsWith('/matches/') && this.props.location.pathname.match('\\d+')) {
      steps = matchSteps
    }

    return (
      <>
        <Joyride
          callback={this.callback}
          run={run}
          stepIndex={stepIndex}
          steps={steps}
          continuous
          disableOverlayClose
          spotlightClicks
          showSkipButton
          locale={{
            back: <span>Zurück</span>,
            last: (<span>Beenden</span>),
            next: (<span>Weiter</span>)
          }}
        />
      </>
    )
  }
}



class Parent extends Component {
  constructor (props) {
    super(props)
    this.handler = this.handler.bind(this)
    this.state = {
      run: true,
      stepIndex: 0,
    }
  }

  handler () {
    this.setState({ run: true, stepIndex: 0 })
  }
render () {
    return (
    //some other stuff
        <RestartButton handler={this.handler} />
        <Tutorial run={this.state.run} stepIndex={this.state.stepIndex} />
    //some other stuff
    )
  }
}



class RestartButton extends React.Component {
  render () {
    return (
      <button className='restartButton' onClick={() => this.props.handler()}>click</button>
    )
  }
}

1 个答案:

答案 0 :(得分:0)

如果state.runstate.stepIndex总是与props.runprops.stepIndex相同,则不应在子组件状态下存储道具。相反,当需要在render方法中使用它们时,应该直接使用它们。 stepIndex={this.props.stepIndex}将与设置子组件的state.stepIndex等于props.stepIndex然后传递stepIndex={this.state.stepIndex}完全相同的值传递给Joyride组件。

如果要从子组件更改父组件状态的值,则可以将处理程序方法(绑定到父组件)传递给所需的任意数量的组件层,或传递给尽可能多的不同子组件你想要的。

class Tutorial extends React.Component {
    constructor(props) {
      super(props)
    }

    render() {
        return ( 
          <>
            <RestartButton handler={this.props.handler}/>
            <Joyride
              callback={this.callback}
              run={this.props.run}
              stepIndex = {this.props.stepIndex}
              steps={steps}
              continuous
              disableOverlayClose
              spotlightClicks
              showSkipButton
              locale={{
                back: < span > Zurück < /span>,
                last: ( < span > Beenden < /span>),
                next: ( < span > Weiter < /span>)
              }}
            />
          </>
        )
    }
}



class Parent extends Component {
  constructor(props) {
    super(props)
    this.handler = this.handler.bind(this)
    this.state = {
      run: true,
      stepIndex: 0,
    }
  }

  handler() {
    this.setState({run: true, stepIndex: 0})
  }

  render() {
    return (
      <Tutorial
        run={this.state.run}
        stepIndex={this.state.stepIndex}
      />
    )
  }
}



class RestartButton extends React.Component {
  render() {
    return (
      <button
        className='restartButton'
        onClick={() => this.props.handler()}
      > click </button>
    )
  }
}

(此外,componentWillReceiveProps is deprecated,如果确实需要进行组件更新,则应该改用componentDidUpdate)。

相关问题