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 将用户发送到带有唯一 recipeIdShowRecipe 组件。

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 创建多个&lt;Card key=recipeId recipeName=recipeName recipeDetail=recipeDetail /&gt; 组件。

为简单起见可能如下所示:

<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.js 的功能组件中首次渲染之前调用 api

react-redux s-s-r 异步 api 调用未按预期工作

使用 react-redux 连接功能时渲染组件上的打字稿错误

子组件API获取请求后重新渲染App组件?

使用 react-routerv4 从 react-redux 应用程序中的状态渲染组件时出现 404 错误?