Я знаю, как переключать класс в React, и я знаю, как сделать класс активным. Однако я не могу понять, как соединить их вместе.

Я наносил на карту свои рецепты и рендерил каждый. Я хочу расширить рецепт после его нажатия, а затем при повторном нажатии вернуться в свое естественное состояние. но если у меня открыт рецепт, и я нажимаю «развернуть» другой, то он должен закрыть первый, а затем развернуть новый.

Это весь мой компонент:

state = {
    term: '',
    selectedRecipeId: 0
  }

  handleInput = (e) => {
    const { value } = e.target;
    this.setState({term: value})
  }

  expandRecipe = (recipeId) => {
    this.setState({ selectedRecipeId: recipeId })
  }

  renderExpandedView = (recipe) => {
    if (this.state.selectedRecipeId === recipe.id){
      return 'recipeContainerExpanded'
    }
    else {
      return null
    }
  }

  resetView = () => {
    this.setState({selectedRecipeId: 0})
  }

  render(){
    const { recipes } = this.props;
    const { term } = this.state;
    return (
      <div>
        <h1>Recipes</h1>
        <button onClick={this.resetView}>Reset View</button>
        <input onChange={this.handleInput} />
        <div className="recipesContainer">
          {recipes.filter(recipe => recipe.name.toLowerCase().includes(term.toLowerCase()) || recipe.ingredients.some(ingredient => ingredient.startsWith(term.toLowerCase()))).map((recipe, index) => (
            <div key={index} className={`recipeContainer ${this.renderExpandedView(recipe)}`}>
              <h3>{recipe.name}</h3>
              <button onClick={() => this.expandRecipe(recipe.id)}>Expand</button>
              <h4>Ingredients</h4>
              <p>{recipe.ingredients.map(ingredient => <p>{ingredient}</p>)}</p>
            </div>
          ))}
        </div>
      </div>
    )
  }

Этот код расширит рецепт, а затем, если вы нажмете другой, он раскроет этот и закроет предыдущий. Я просто хочу добавить функциональность, которая при втором щелчке закрывает этот рецепт, но я не могу понять, как это сделать, не применяя javascript к каждому рецепту.

Надеюсь, что это имеет смысл

0
The Walrus 23 Фев 2018 в 14:47

3 ответа

Лучший ответ

Вы можете извлечь рецепт в компонент Рецепт и использовать метод жизненного цикла shouldComponentUpdate , чтобы React узнал, не влияет ли на выход компонента текущие изменения.

export default class Recipe extends Component {
expandRecipe = () => {
    const {onExpand, recipe, isExpanded} = this.props;

    onExpand(isExpanded ? null : recipe.id);
};

shouldComponentUpdate(nextProps) {
    const {isExpanded} = this.props;

    return isExpanded !== nextProps.isExpanded;
}

render() {
    const {recipe, isExpanded} = this.props;

    return (
        <div className={`recipeContainer ${isExpanded ? 'recipeContainerExpanded' : ''}`}>
            <h3>{recipe.name}</h3>
            <button onClick={this.expandRecipe}>Expand</button>
            <h4>Ingredients</h4>
            <p>{recipe.ingredients.map(ingredient => <p>{ingredient}</p>)}</p>
        </div>
    )
}
}

Просьба проверить демонстрационную версию

0
Igor Alemasow 23 Фев 2018 в 12:45

Создайте отдельный компонент, который будет отвечать за возможность расширения.

Expandable.js

class Expandable extends React.PureComponent {
constructor() {
super();
this.state = {
  isExpand: true,
  selectedRecipeId: 0,
};
this.togglePar = :: this.expandRecipe;
}
expandRecipe(recipeId) {
this.setState({
  isExpand: !this.state.isPar,
  selectedRecipeId: recipeId,
});
}
render() {
 return (
  <div>
    <h3>{this.props.name}</h3>
    <button onClick={() => this.expandRecipe(this.props.id)}>Expand</button>
    {this.state.isExpand && <div>
      <h4>Ingredients</h4>
      <p>{this.props.ingredients.map(ingredient => <p>{ingredient}</p>)}</p>
      </div>
     }
    </div>
   );
  }
}

ActualComponent

  render() {
  const { recipes } = this.props;
  const { term } = this.state;
  return (
  <div>
    <h1>Recipes</h1>
    <button onClick={this.resetView}>Reset View</button>
    <input onChange={this.handleInput} />
    <div className="recipesContainer">
      {recipes.filter(recipe => 
      recipe.name.toLowerCase().includes(term.toLowerCase()) || 
      recipe.ingredients.some(ingredient => 
      ingredient.startsWith(term.toLowerCase()))).map((recipe, index) => (
        <Expandable key={index} props... />
      ))}
    </div>
  </div>
 )
}
0
Muneeb 23 Фев 2018 в 12:51

Я только что сделал демонстрацию с моими предположениями, проверьте ссылку: demo

Это тебе нужно? или дайте мне больше деталей, чтобы решить эту проблему

0
Jayavel 23 Фев 2018 в 12:14