react-redux:在 API 调用后渲染组件
Posted
技术标签:
【中文标题】react-redux:在 API 调用后渲染组件【英文标题】:react-redux: Rendering a component after an API call 【发布时间】:2019-02-20 18:35:50 【问题描述】:我正在构建一个使用用户输入并显示食谱数量的应用程序,他们也可以单击食谱卡来查看成分。每次他们点击配方卡时,我都会调用 API 来获取合适的配方成分。但我无法弄清楚如何显示包含配方成分的组件。我也尝试了条件路由和条件渲染,但找不到解决方案。
Recipe_Template.js
export class RecipeTemplate extends Component
renderRecipe = recipeData =>
return recipeData.recipes.map(recipeName =>
return (
<div className="container">
<div className="row">
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<a
href=recipeName.source_url
target="_blank"
onClick=() =>
this.props.fetchRecipeId(recipeName.recipe_id);
>
<img
src=recipeName.image_url
className="mx-auto d-block img-fluid img-thumbnail"
alt=recipeName.title
/>
<span>
<h3>recipeName.title</h3>
</span>
</a>
<span>
<h3>recipeName.publisher</h3>
</span>
</div>
</div>
</div>
);
);
;
render()
return (
<React.Fragment>
this.props.recipe.map(this.renderRecipe)
</React.Fragment>
);
Recipe_Detail.js
class RecipeDetail extends Component
renderRecipeDetail(recipeData)
return recipeData.recipe.ingredients.map(recipeIngredient =>
return <li key=recipeIngredient>recipeIngredient</li>;
);
render()
if (this.props.recipeId === null)
return <div>Loading...</div>;
return <ul>this.props.recipeId.map(this.renderRecipeDetail)</ul>;
function mapStateToProps( recipeId )
return recipeId ;
export default connect(mapStateToProps)(RecipeDetail);
【问题讨论】:
【参考方案1】:不完全确定为什么在这里需要 Redux(除非它在其他嵌套组件之间共享),但我相当肯定你可以只使用 React 状态。
一种方法是这样配置您的路线:
<Route path="/recipes" component=Recipes />
<Route path="/recipe/:id" component=ShowRecipe />
当用户发送一个查询,得到一些结果,你将所有匹配的配方显示到一个Recipes
组件。然后每个recipe
都有一个名称(和其他相关的可显示数据)和一个可点击的链接:
<Link to=`/recipe/id?recipeId=$recipeId`>View recipeName Recipe</Link>
为简单起见可能如下所示:
<ul>
<Link to="/recipe/id?recipeId=08861626">View Prosciutto Bruschetta Recipe</Link>
<Link to="/recipe/id?recipeId=04326743">View Pasta Bundt Loaf Recipe</Link>
...etc
</ul>
当用户点击链接时,react-router 将用户发送到带有唯一 recipeId
的 ShowRecipe
组件。
ShowRecipe 然后发出另一个 AJAX 请求以获取配方详细信息:
ShowRecipe.js
export default class ShowRecipe extends Component
state = recipeDetail: ''
componentDidMount = () =>
const recipeId = this.props.location.query; // <== only natively available in react-router v3
fetch(`http://someAPI/recipe/id?recipeId=$recipeId`)
.then(response => response.json())
.then(json => this.setState( recipeDetail: json ));
render = () => (
!this.state.recipeDetails
? <div>Loading...</div>
: <ul>
this.state.recipeDetail.map(ingredient => (
<li key=ingredient>ingredient</li>
)
</ul>
)
另一种方法:
将recipeDetails
存储在原始提取的recipes
JSON 中并可用。然后映射recipes
并为每个recipe
创建多个<Card key=recipeId recipeName=recipeName recipeDetail=recipeDetail />
组件。
为简单起见可能如下所示:
<div>
this.state.recipes.map((recipeId, recipeName, recipeDetail), => (
<Card key=recipeId recipeName=recipeName recipeDetail=recipeDetail />
)
</div>
那么每张卡片都有自己的状态:
Card.js
export default class Card extends Component
state = showDetails: ''
toggleShowDetails = () => this.setState(prevState => ( showDetails: !this.state.showDetails ))
render = () => (
<div>
<h1>this.props.recipeName Recipe</h1>
<button onClick=toggleShowDetails> `$!this.state.showDetails ? "Show" : "Hide" Recipe<button>
this.state.showDetails &&
<ul>
this.props.recipeDetail.map(ingredient => (
<li key=ingredient>ingredient</li>
)
</ul>
)
因此,默认情况下recipeDetail
已经存在,但被隐藏了。然而,当用户点击卡片的按钮时,它会将卡片的showDetails
状态切换为true/false
以显示/隐藏配方详情。
【讨论】:
非常感谢。我选择了第二种方式。再次感谢。以上是关于react-redux:在 API 调用后渲染组件的主要内容,如果未能解决你的问题,请参考以下文章
API 调用后 React/Flux seState 不重新渲染组件
react-redux s-s-r 异步 api 调用未按预期工作