response-redux: рендеринг компонента после вызова API - PullRequest
0 голосов
/ 16 сентября 2018

Я создаю приложение, которое использует пользовательский ввод и показывает количество рецептов, и они также могут щелкнуть карточку рецепта, чтобы просмотреть ингредиенты. Каждый раз, когда они нажимают на карточку рецепта, я делаю вызов 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 Ответ

0 голосов
/ 16 сентября 2018

Не совсем уверен, зачем вам нужен 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>

Когда пользователь нажимает на ссылку, реагирующий маршрутизатор отправляет пользователя на компонент ShowRecipe с уникальным recipeId.

Затем 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 и создайте несколько <Card key={recipeId} recipeName={recipeName} recipeDetail={recipeDetail} /> компонентов для каждого recipe.

для простоты может выглядеть так:

<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, чтобы отобразить / скрыть детали рецепта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...