使用反应路由器反应 HOC
React HOC with react-router
我正在尝试重新使用我的一个反应组件,我的 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>
)
}
可编辑BlogPost.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 之间共享的大量代码。也许我在这里做的事情根本上是错误的,但我不确定最好的方法是什么,感谢您的帮助。
似乎对 HOC 到底是什么存在一些误解。 HOC 是一个函数,它接受一个组件,然后 returns 一个组成该组件的新组件。 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} />
我正在尝试重新使用我的一个反应组件,我的 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>
)
}
可编辑BlogPost.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 之间共享的大量代码。也许我在这里做的事情根本上是错误的,但我不确定最好的方法是什么,感谢您的帮助。
似乎对 HOC 到底是什么存在一些误解。 HOC 是一个函数,它接受一个组件,然后 returns 一个组成该组件的新组件。 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} />