从父组件反应更新子状态

时间:2018-03-08 16:29:12

标签: javascript reactjs ecmascript-6

我有一个父组件如下:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import GridItem from './gridItem.js'

class Grid extends Component {
  renderGridItems = () => {
    const gridItems = this.props.gridItems,
          itemsHTML = [];

    for(let i = 1; i < (gridItems + 1); i++){
        itemsHTML.push(
          <GridItem hidden={false} key={i}>{i}</GridItem>
        )
    }

    return itemsHTML
  }
  hideGridItem() {
      console.log('hide single grid item')
  }
  render() {
    return (
      <div className="grid">
        {this.renderGridItems()}
        <button onClick={this.hideGridItem()}>hide random grid item</button>
      </div>
    );
  }
}

Grid.propTypes = {
    renderGridItems: PropTypes.func,
    gridItems: PropTypes.number
}

export default Grid;

和一个孩子:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class GridItem extends Component {
  constructor(props) {
    super(props);

    this.state = {
        hidden: false
    }
  }
  hideGridItem = () => {
    this.setState({ hidden: true })
  }
  render() {
    const hideGridItem = this.state.hidden ? " hide": ""

    return (
      <div className={"gird-item" + hideGridItem}>
        {this.props.children}
      </div>
    );
  }
}

export default GridItem;

在#34; Grid&#34;组件,我想随机(仅限现在)选择一个&#34; gridItem&#34;设置它的隐藏&#34;支持真正的onClick。

3 个答案:

答案 0 :(得分:1)

根据随机选择的网格索引设置隐藏

// may not be the best way to get a random GridItem index
const hidden_i = (Math.floor(Math.random() * gridItems) + 1
for(let i = 1; i < (gridItems + 1); i++){
    itemsHTML.push(
      <GridItem hidden={i == hidden_i} key={i}>{i}</GridItem>
    )
}

答案 1 :(得分:1)

好的,我看到了一个你错的地方。

如果您有一个网格项组件,并且您希望能够显示它并将其取下显示而不是这样做。

this.state= { 
 griditems: [{
 hidden:false,
 description:'first grid item',
 id:1
},
{
 hidden:false,
 description:'second grid item',
 id:2
}, ]
}

现在,当您在顶级组件中创建这样的网格项时,将更容易确定要显示或隐藏的网格项。

在Grid组件中,以下内容应更改

renderGridItems () => {
 const { griditems } = this.props 
 return griditems.map(item => !item.hidden ? <div> {item.id} {item.description} <button onClick={this.hideGridItem(item.id)}> HIDE ME</button> </div> : <div onClick={this.show(item.id)}> show </div>
}

现在在你的hideGridItem中。

hideGridItem(id) => {
 const { griditems } = this.props
 const currentItem = griditems.filter(item => item.id === id);
 currentItem.hidden = true;
 const newitems = griditems.filter(item => item.id !== id)
 newitems.push(currentItem);
 //now call the setter in your parent component which I made below
 this.props.setGridItems(newitems);
}

现在制作一个showGridItem

showGridItem = (id) => {
const { griditems } = this.props
     const currentItem = griditems.filter(item => item.id === id);
     currentItem.hidden = false;
     const newitems = griditems.filter(item => item.id !== id)
     newitems.push(currentItem);
     //now call the setter in your parent component 
     this.props.setGridItems(newitems);
}

回到父母,我们将制作setGridItems

setGridItem (updateditems) => {
 this.setState({ griditems:updateditems });
}

答案 2 :(得分:-1)

您没有在子项目中使用父提供的hidden道具:

const hideGridItem = this.state.hidden ? " hide": ""

应该是:

const hideGridItem = this.props.hidden ? " hide": ""

状态应该是组件的内部,而不是直接从其他组件修改。但无论如何你可能意味着道具。

有了这个道具,你可以在父母那里做这样的事情:

hideGridItem() {
  index = Math.floor(Math.random() * this.props.gridItems.length);
  this.setState({hiddenIndex: index});
}

然后在渲染方法中:

for(let i = 1; i < gridItems.length; i++) {
  itemsHTML.push(
    <GridItem hidden={this.state.hiddenIndex === i} key={i}>{i}</GridItem>);
}

不确定for循环中的表达式(GridItems + 1)是否正在执行您想要的操作。另外,你should not be using the index as a key