【问题标题】:react-redux: Rendering a component after an API callreact-redux:在 API 调用后渲染组件
【发布时间】: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);

【问题讨论】:

    标签: reactjs react-redux conditional-rendering


    【解决方案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 以显示/隐藏配方详情。

    【讨论】:

    • 非常感谢。我选择了第二种方式。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 2017-02-10
    • 2018-03-24
    • 1970-01-01
    • 1970-01-01
    • 2017-10-05
    相关资源
    最近更新 更多