【问题标题】:React HOC with react-router用 react-router 反应 HOC
【发布时间】:2018-09-11 03:07:36
【问题描述】:

我正在尝试重用我的一个反应组件,我的 BlogPost 和 EditableBlogPost 组件都需要对后端进行提取以获取相同的数据。我想使用高阶组件来执行此操作,但我不确定如何使用 react-router 来完成此操作,因为我正在直接路由到这些组件。 HOC 没有被触发,我无法在我想要的地方进行获取。理想情况下,路由器会渲染 HOC,然后将数据传递给我认为的 BlogPost 和 EditableBlogPost 组件?

代码:

Home.js

  render () {
    return (
      <Switch>
        <Route
          exact
          path={`${this.props.match.url}/:id`}
          component={BlogPost} // id like to use a HOC here to fetch data and pass it down to the BlogPost but i cant do it from within this file.
        />
        <Route
          exact
          path={`${this.props.match.url}/:id/edit`}
          component={EditableBlogPost} // id like to use a HOC here to fetch the data as well and pass it down.
        />
        <Route
          exact
          path={`${this.props.match.url}/new/post`}
          render={() => {
            return <EditableBlogPost isNew />
          }}
        />
        <BlogSummaryContainer posts={this.state.blogPosts} />
      </Switch>
    )
  }

BlogPost.js

class BlogPost extends Component {
  render () {
    console.log(this.props.match.params.id)
    console.log('this.props', this.props)
    const { classes, title, content } = this.props

    return (
      <Card className={classes.card}>
        <CardMedia
          className={classes.media}
          image='/static/images/cards/contemplative-reptile.jpg'
          title='bang'
        />
        <CardContent>
          <Typography className={classes.title}>{title}</Typography>
          <Typography variant='headline'>{title}</Typography>
          <Typography className={classes.pos}>adjective</Typography>
          <Typography variant='body1'>{content}</Typography>
        </CardContent>
        <CardActions>
          <Button
            size='small'
            component={Link}
            to={`${this.props.match.url}/edit`}
          >
            Edit
          </Button>
        </CardActions>
      </Card>
    )
  }

EditableBlogPost.js

  render () {
    const { classes } = this.props
    console.log(this.state)
return (
   ...other code...
    </CardActions>
    <Divider />
    <Typography variant='headline'>Preview</Typography>
    <CardMedia
      className={classes.media}
      image={this.state.file[0].preview}
      title='bang'
    />
    <CardContent>
      <Typography className={classes.title}>
        {this.state.title || 'Title'} // id like this to use props from HOC 
      </Typography>
      <Typography variant='headline'>
        {this.state.title || 'Title'}
      </Typography>
      <Typography className={classes.pos}>
        {this.state.catchPhrase || 'CatchPhrase'}
      </Typography>
      <Typography variant='body1'>
        {this.state.content || 'Content'}
      </Typography>
    </CardContent>
    //this is where <BlogPost> should be instead of duplicating code.
   ...
)

BlogPostContainer.js(我尝试使用的 HOC)

class BlogPostContainer extends Component {
  constructor () {
    super()
    this.state = { title: '', content: '' }
  }

  componentDidMount () {
    fetch(`/api/posts/${this.props.match.params.id}`)
      .then(res => {
        return res.json()
      })
      .then(blogPost => {
        // console.log('blogPost', blogPost)

        this.setState({
          title: blogPost.title,
          content: blogPost.content
        })
      })
  }

  render () {
    return <BlogPost title={this.state.title} />
  }

如果我能够以某种方式向下传递获取数据,我可以删除大量在 BlogPost 和 EditableBlogPost 之间共享的代码。也许我在这里做一些根本错误的事情,但我不确定最好的方法是什么,感谢任何帮助。

【问题讨论】:

    标签: javascript reactjs react-router state react-props


    【解决方案1】:

    似乎对 HOC 的实际含义存在一些误解。 HOC 是一个函数,它接受一个组件,然后返回一个组成该组件的新组件。 See this guide for more info.

    // HOCs are usually written with `with` at the beginning
    function withBlogPostData(WrappedComponent) {
      return class BlogPostContainer extends React.Component {
        constructor() {
          super()
          this.state = { title: "", content: "" }
        }
    
        componentDidMount() {
          fetch(`/api/posts/${this.props.match.params.id}`)
            .then(res => {
              return res.json()
            })
            .then(blogPost => {
              // console.log('blogPost', blogPost)
    
              this.setState({
                title: blogPost.title,
                content: blogPost.content,
              })
            })
        }
    
        render() {
          return <WrappedComponent title={this.state.title} />
        }
      }
    }
    
    // Create a new component like so
    // This way, BlogPost can access the prop `title` given to it by the HOC
    const BlogPostWithData = withBlogPostData(BlogPost)
    
    // Then use it in your routes:
    <Route component={BlogPostWithData} />
    

    Also look into render props as a more flexible alternative.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-04
      • 1970-01-01
      • 1970-01-01
      • 2019-02-05
      • 2018-02-15
      • 2021-05-11
      • 1970-01-01
      相关资源
      最近更新 更多