在 React 中切换 class 并设置活动的 class
Toggling a class and setting an active class in React
我知道如何在 React 中切换 class,我知道如何激活 class。但是,我不知道如何将它们放在一起。
我映射我的食谱并渲染每一个。我想在点击菜谱后展开它,如果再次点击 return 到它的自然状态。但是如果我打开了一个菜谱,然后点击展开另一个菜谱,那么它应该会关闭第一个菜谱,然后展开新菜谱。
这是我的全部组成部分:
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 应用于每个食谱,我无法解决该问题。
希望有道理
我刚刚用我的假设做了一个演示检查 link :
demo
你需要吗?或者给我更多的细节来解决这个问题
您可以将配方提取到 Recipe 组件并使用 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>
)
}
}
请检查 demo
创建单独的组件,负责扩展。
Expandalbe.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>
)
}
我知道如何在 React 中切换 class,我知道如何激活 class。但是,我不知道如何将它们放在一起。
我映射我的食谱并渲染每一个。我想在点击菜谱后展开它,如果再次点击 return 到它的自然状态。但是如果我打开了一个菜谱,然后点击展开另一个菜谱,那么它应该会关闭第一个菜谱,然后展开新菜谱。
这是我的全部组成部分:
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 应用于每个食谱,我无法解决该问题。
希望有道理
我刚刚用我的假设做了一个演示检查 link : demo
你需要吗?或者给我更多的细节来解决这个问题
您可以将配方提取到 Recipe 组件并使用 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>
)
}
}
请检查 demo
创建单独的组件,负责扩展。
Expandalbe.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>
)
}