您好,我是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>
)
}
}
答案 0 :(得分:0)
如果state.run
和state.stepIndex
总是与props.run
和props.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)。