简体   繁体   English

用react-router反应HOC

[英]React HOC with react-router

I'm trying to re-use one of my react components, both my BlogPost and EditableBlogPost components need to make a fetch to the backend to get the same data. 我正在尝试重新使用我的一个反应组件,我的BlogPost和EditableBlogPost组件都需要对后端进行提取以获取相同的数据。 Id like to use a Higher Order Component to do this, but im unsure how to accomplish this with react-router because im am routing directly to those components. 我喜欢使用更高阶的组件来执行此操作,但我不确定如何使用react-router实现此目的,因为我正在直接路由到这些组件。 The HOC isnt triggered and im not able to make the fetch where i want to. HOC没有被触发,我无法在我想要的地方进行获取。 Ideally the router would render the HOC and then pass the data down to the BlogPost and EditableBlogPost components I think? 理想情况下,路由器将呈现HOC,然后将数据传递给我认为的BlogPost和EditableBlogPost组件?

Code: 码:

Home.js 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 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 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 (the HOC im trying to use) 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} />
  }

If im able to pass the fetch data down somehow i can remove a lot of code that is shared between BlogPost and EditableBlogPost. 如果我能够以某种方式向下传递获取数据,我可以删除BlogPost和EditableBlogPost之间共享的大量代码。 Maybe i'm doing something fundamentally wrong here but im not sure exactly what the best way to do this is, any help is appreciated. 也许我在这里做了一些根本性的错误,但我不确定最好的方法是做什么,任何帮助都表示赞赏。

It seems there's some misunderstanding in what an HOC actually is. 似乎HOC实际上存在一些误解。 An HOC is a function which accepts a component, then returns a new one composing that component. 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. 另外,将渲染道具视为更灵活的替代方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM