将道具传递给克隆的子元素,给出“未知道具”警告

时间:2017-01-11 21:39:21

标签: reactjs react-bootstrap

我有一个AdminLayout in react,它反过来以这种方式加载子元素:

class AdminLayout extends Component {

  constructor(props){
    super(props)
    this.state = {
      flash: { msg: "some message", type: undefined}
    }
  }

  updateFlash(flash){
    this.state.flash = flash
  }

  render() {
    return(
      <div>
        <FlashMessage flash={this.state.flash} />
        <NavBar/>
        { React.cloneElement(this.props.children, {updateFlash: this.updateFlash})}
      </div>
    )
  }
}

这里的想法是我打算让我的子元素更新AdminLayout中的flash状态。但是,使用代码{updateFlash: this.updateFlash},我收到以下错误:

Warning: Unknown prop `updateFlash` on <div> tag. Remove this prop from the element. For details, see https://facebook.github.io/react/warnings/unknown-prop.html
    in div (created by Grid)
    in Grid (created by LocationEdit)

我查看了文档,我不相信我在做任何案例。我也没有尝试直接在任何div上设置道具。

有没有人见过这样的东西?

Hrm ......也许有助于了解我的内部组件是什么样的。我试图挑出任何不必要的......:

import React, {Component} from 'react'
import AdminLayout from '../components/layouts/AdminLayout'
import LocationsSource from '../sources/LocationsSource'
import {Button, Grid, Row, Col, FormGroup, FormControl, ControlLabel, HelpBlock} from 'react-bootstrap'
import { browserHistory } from 'react-router'

class LocationEdit extends Component {

  constructor(props) {
    super(props)
    this.handleSubmit = this.handleSubmit.bind(this)

    this.state = {
      loading: true,
      location: {
        name: "",
        site_link: "",
        description: ""
      }
    }
  }

  handleSubmit = (event) => {
    event.preventDefault()

    let data = this.state.location

    if(data._id != undefined) {
      LocationsSource.update(data).then((response) => {
        browserHistory.push('/admin/locations/');
      })
    } else {
      LocationsSource.create(data).then((response) => {
        browserHistory.push('/admin/locations/');
      })
    }
  }

  componentDidMount() {
    if(this.props.params.id)
      LocationsSource.find(this.props.params.id).then((result) => {
        this.setState({loading: false, location: result})
      })
    else{
      this.setState({loading: false, location: {}})
    }
  }

  handleChange = (event) => {
    let change = {location: this.state.location}
    change['location'][event.target.name] = event.target.value
    this.setState(change)
  }

  componentWillUnmount() {}

  render() {
    let location = this.state.location

    if(this.state.loading)
      return(
        <AdminLayout>
          <Row>
            <img src="/assets/images/loading.gif" />
          </Row>
        </AdminLayout>
      )
    else
      return(
        <AdminLayout>
          <Grid>
            <Row>
              <Col xs={8} md={8}>
                <h2>Location</h2>
              </Col>
            </Row>
            <Row>
              <Col xs={8} md={8}>
                <form onSubmit={this.handleSubmit}>
                  <FormGroup controlId={"name"}>
                    <ControlLabel>Name:</ControlLabel>
                    <FormControl onChange={this.handleChange} name="name" type="text" defaultValue={location.name} />
                  </FormGroup>
                  <Button type="submit">
                    Submit
                  </Button>
                </form>
              </Col>
            </Row>
          </Grid>
        </AdminLayout>
      )

  }
}

export default LocationEdit

2 个答案:

答案 0 :(得分:0)

  updateFlash(flash){
    this.setState({ flash });
  }

  render() {
    return(
      <div>
        <FlashMessage flash={this.state.flash} />
        <NavBar/>
        { React.cloneElement(this.props.children, {updateFlash: this.updateFlash.bind(this)})}
      </div>
    )
  }

答案 1 :(得分:0)

好的,问题的根源是我正在使用react-router错误。直到我添加问题的最后一部分,它才显示我正在从子组件AdminLayout呈现LocationEdit,这是不可能看到的。

我这样做是因为我正在反应路由器直接加载该页面,我没有意识到我实际上需要首先加载布局,并且需要将子页面定义为子标签。接下来是我的原始路线和我所做的改变:

render((
  <Router history={browserHistory}>
    <Route path="/admin/" component={Locations} />
    <Route path="locations" component={LocationEdit} />
  </Router>
), document.getElementById('app'));

的变化:

render((
  <Router history={browserHistory}>
    <Route path="/admin/" component={AdminLayout} >
      <Route path="locations" component={LocationEdit} />
    </Route>
  </Router>
), document.getElementById('app'));

然后我从我的LocationEdit页面中取出了AdminLayout标签。我觉得它试图将props直接加载到<Grid>标记上,而不是按照我的想法加载到实际组件上。