【问题标题】:Reusing multiple instances of react component with different props使用不同的 props 重用多个 react 组件实例
【发布时间】:2019-05-27 03:36:47
【问题描述】:

所以我有一个子组件,我想在父容器组件中呈现多个实例。将不同的道具传递给每个道具,以便它们以不同的方式显示。

发生的情况是它们都被渲染,脚本中的道具的最后一个实例被读入两个实例。因此,下面的两个组件都以 placeHolder==='Describe yourself' 结尾 有没有办法解决这个问题,以便他们每个人都被专门注入他们的道具?

           <ButtonMode 
              open={this.state.open}
              handleClose={this.handleClose}
              buttonName='Update'
              modalOpen={this.modalOpen}    
              placeHolder="New picture url"
              change={this.handlePicture}
              label='URL'
            />

           <ButtonMode 
              open={this.state.open}
              handleClose={this.handleClose}
              buttonName='Update'
              modalOpen={this.modalOpen}     
              placeHolder='Describe yourself'
              label='Bio'
              change={this.handleBio}
                />

按钮模式

class ButtonMode extends Component {
    constructor(props){
        super(props)
        this.state = {
            input:''
        }
        this.handleInput = this.handleInput.bind(this);
        this.handle = this.handle.bind(this);
    }

    handleInput(val){
        this.setState({input:val})
    };

    handle() {

        this.props.change(this.state.input);
    };

    render(){
        const { classes } = this.props;
        return (
            <div>
                <Button 
                    className={classes.button}
                    onClick={this.props.modalOpen}
                    >Update
                </Button>
                <Modal
                    aria-labelledby="simple-modal-title"
                    aria-describedby="simple-modal-description"
                    open={this.props.open}
                    onClose={this.props.handleClose}
                    >
                    <div className={classes.paper}>
                        <TextField
                            id="filled-textarea"
                            label={this.props.label}
                            placeholder={this.props.placeHolder}
                            multiline
                            className={classes.textField}
                            onChange={(e)=>{this.handleInput(e.target.value)}}
                            rows= '4'
                            />
                        <Button 
                            onClick={this.handle}
                            className={classes.button} 
                            color="secondary">Submit</Button>                  
                  </div>
                </Modal>
            </div>
        )
    }
}

然后我就这样用了

 class UserCard extends Component {
    constructor(props){
        super(props);
        this.state = {
          tempPro:'',
          open: false,
          profilePicture:''
        }
        this.modalOpen = this.modalOpen.bind(this);
        this.handleClose = this.handleClose.bind(this);
        this.handlePicture = this.handlePicture.bind(this);
      }



    // componentDidMount(){
    //   const {userId, profilePic} = this.props;
    //   this.setState({profilePicture:profilePic});
    //   // axios.get(`/api/profile/${userId}`).then(res=>{

    //   //   let {profilePic} = res.data[0];
    //   //   this.setState({profilePic})
    //   // })
    // }


    handlePicture(val){
      this.props.changePic(val);
      this.setState({open:false});
    };

    handleBio(val){

      this.setState({open:false});
    };

    handleClose(){
        this.setState({open: false});
    };
    modalOpen(){
      this.setState({open:true});
    };

    render() {
      const { classes } = this.props;
      const {stories} = this.props;
      let storyShow = stories.map((story,id) => {
        return(
          <div value={story.story_id}>
              <h3>{story.title}</h3>
              <ul className={classes.background}>
                <li>{story.description}</li>
                <li>{story.is_complete}</li>
              </ul>  
          </div>
        )
      });

      return (  
      <div className={classes.rootD}>
        <Grid container>
          <Grid className={classes.itemFix} >
          <Card className={classes.card}>
           <CardMedia
            className={classes.media}
            image={this.props.proPic}
            title={this.props.userName}
            />
            <div>
            <ButtonMode 
                  open={this.state.open}
                  handleClose={this.handleClose}
                  modalOpen={this.modalOpen}    
                  placeHolder="New picture url"
                  change={this.handlePicture}
                  label='URL'
                />
            </div>       
          <CardHeader
            className={classes.titles}
            title={this.props.userName}
            subheader="Somewhere"
            />
            <CardHeader className={classes.titles} title='Bio' />
              <CardContent className={classes.background}>
                <Typography className={classes.bio} paragraph>
                  {this.props.bio}
                </Typography>
              </CardContent> 
              <div>
                <ButtonMode 
                  open={this.state.open}
                  handleClose={this.handleClose}
                  modalOpen={this.modalOpen}     
                  placeHolder='Describe you how you want'
                  label='Bio'
                  change={this.handleBio}
                    />
              </div>
          </Card>
          </Grid>
          <Grid className={classes.itemFixT}>
            <Card className={classes.card}>
            <CardContent>
                <CardHeader 
                  className={classes.titles}
                  title='Works'/>
                <Typography paragraph>
                  <ul>
                    {storyShow}
                  </ul>
                </Typography>
              </CardContent>
            </Card>
          </Grid>
          </Grid>
      </div>
      );
    }
  }

  UserCard.propTypes = {
    classes: PropTypes.object.isRequired,
  };
  function mapStateToProps(state){
    const {userId, profilePic} = state;
    return {
      userId,
      profilePic      
    }
  }

  export default connect(mapStateToProps,{})(withStyles(styles)(UserCard));

【问题讨论】:

  • React 实际上的工作方式是允许您拥有具有不同props 的同一组件的多个实例。所以他们的代码应该有问题。也许它们被有缺陷的 HOC 包裹着,或者由于某种原因 props 进入了 static 属性。添加组件的代码。
  • 您能否发布整个组件以及ButtonMode 组件?
  • @jsw324 刚刚做了。感谢您的新鲜眼睛。
  • @skyboyer 我正在使用 Material UI。但我以前做过类似的事情,没有任何问题。
  • 目前看来一切正常。你有没有试过把ButtonMode直接省略UserCard?我相信你应该让它正常工作。这样你就可以开始调试了。

标签: reactjs reusability react-props react-component


【解决方案1】:

我在类似的问题上花了很长时间,令人尴尬。我尝试了各种 JS 调试,甚至重新阅读了闭包的整个概念:)

这是我的罪魁祸首:&lt;TextField id="filled-textarea" ... /&gt;

id 是静态的。如果我们在一页上有多个相同id 的实例,我们就有问题了。

使id 动态化,例如&lt;TextField id={this.props.label} ... /&gt;

【讨论】:

    【解决方案2】:

    我有一个类似的问题,我试图将不同的函数传递给子组件。我有一个 UploadFile 组件,其中包含来自 material-ui 的 &lt;input/&gt;&lt;Button/&gt;,我想在整个页面中多次重用这个组件,因为用户有多个文件要上传,并且为了保存文件,我需要在主页面的回调函数。

    我必须做的是,在我的情况下给每个子组件&lt;UploadFile/&gt;,在你的情况下给&lt;ButtonMode/&gt;,一个 unique id 作为道具传入,否则,顶部级别页面无法区分对子组件的每个引用。

    子组件的代码:

    function UploadFile({ value, handleFile }) {
    const classes = useStyles();
    
    return (
    <>
      <input
        accept=".tsv,.fa,.fasta"
        className={classes.input}
        id={value}
        type="file"
        style={{ display: 'none' }}
        onChange={e => handleFile(e.target.files[0])}
      />
      <label htmlFor={value}>
        <Button
          variant="contained"
          color='default'
          component="span"
          startIcon={<CloudUploadIcon />}
          className={classes.button}>
          Upload
        </Button>
      </label>
    </>
    );
    }
    

    这个组件在父组件中的用法(handleFile是我传入的函数,上面定义在父组件中):

    <UploadFile value='prosite' handleFile={handlePrositeFile} />
    <UploadFile value='pfam' handleFile={handlePfamFile} />
    

    【讨论】:

      【解决方案3】:

      我对两个模态都使用相同的状态,并且在每个 handleOpen() 实例中它只打开脚本中的最后一个模态实例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-03
        • 2023-03-23
        • 2022-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-07
        • 2016-09-30
        相关资源
        最近更新 更多