React - JSX 语法问题,以及如何迭代地图并在换行符上显示项目

IT技术 javascript reactjs iteration jsx array.prototype.map
2021-04-30 04:56:28

我是一个 React 菜鸟,正在制作一个 ToDo 列表样式的Recipe List 应用程序我有一个功能组件 Item.js,我使用 JSX 和 map 函数遍历每个配方项并显示它们。我希望每个菜谱项都出现在一个新行上,但是当我使用 .map 遍历它们时,React 会将整个菜谱项列表放入一个 p 标记中,而不是每个项的一个 p 标记中。

如何遍历配方项并将它们显示在不同的行上?即使我尝试将它们显示为无序列表,React 也希望将每个项目放入一个 li 标签中。

这是我的代码:

import React from 'react';
import Button from 'react-bootstrap/lib/Button';


const Item = (props) => (
  <div>
    <div className="Recipe-Item-Container" key={props.text}>

        {props.items.map((item, index) => 
        <div className="Recipe-Item" key={index}>

            <h3>{item}</h3>

            <p>{props.ingredients[index]}</p>

          <div className="buttons-container">
            <Button className="edit-button" onClick={() => props.edit(item, index)}>Edit</Button>
            <Button className="delete-button" onClick={() => props.delete(item, index)}>Delete</Button>
          </div>

        </div>
      )}
    </div>
  </div>
)


export default Item;

也对{props.items.map((item, index) => ,如果我以后添加大括号线=>我得到一个错误。我安装了 React/JSX linter,但它没有捕捉到任何东西。有什么问题?

我知道这可能是一个菜鸟错误,但 JSX 在这里让我循环。

2个回答

如果在粗箭头后添加花括号,则必须显式返回JSX.

const Item = (props) => (
  <div>
    <div className="Recipe-Item-Container" key={props.text}>

      {props.items.map((item, index) => {
          return (
              <div className="Recipe-Item" key={index}>

              <h3>{item}</h3>

              <p className="ingredients-list">
                   {props.ingredients[index].map((ingredient, ingredientIndex) => {
                      return (
                           <div className="ingredient" key={ingredient}>
                               {ingredient}
                           </div>
                     )
                   }}
              </p>

              <div className="buttons-container">
                <Button className="edit-button" onClick={() => props.edit(item, index)}>Edit</Button>
                <Button className="delete-button" onClick={() => props.delete(item, index)}>Delete</Button>
              </div>

            </div>
          )
        }
      )}
    </div>
  </div>
)

这是工作版本。

class App extends React.Component {
  state = {
    items: [ "Pumpkin Pie", "Spaghetti", "Onion Pie" ],
    ingredients: [
      [ "Pumpkin Puree", "Sweetened Condensed Milk", "Eggs", "Pumpkin Pie Spice", "Pie Crust" ],
      [ "Noodles", "Tomatoe", "Sauce", "Meatballs" ],
      [ "Onion", "Pie Crust" ],
    ],
  }

  render() {
    return (
      <div className="box">
        <Item items={this.state.items} ingredients={this.state.ingredients} />
      </div>
    );
  }
}

const Item = props => (
  <div>
    <div className="Recipe-Item-Container" key={props.text}>

      {props.items.map( ( item, index ) => (
        <div className="Recipe-Item" key={item}>

          <h3>{item}</h3>
          <ul>
            {
              props.ingredients[ index ].map( ingredient =>
                <li key={ingredient}>{ingredient}</li> )
            }
          </ul>


          <div className="buttons-container">
            <button className="edit-button" onClick={() => props.edit( item, index )}>Edit</button>
            <button className="delete-button" onClick={() => props.delete( item, index )}>Delete</button>
          </div>

        </div>
      ) )}
    </div>
  </div>
);

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

但如果我是你,我会改变我的状态。类似的东西:

class App extends React.Component {
  state = {
    items: [
      {
        name: "Pumpkin Pie",
        ingredients: [
          "Pumpkin Puree",
          "Sweetened Condensed Milk",
          "Eggs",
          "Pumpkin Pie Spice",
          "Pie Crust"
        ]
      },
      {
        name: "Spaghetti",
        ingredients: ["Noodles", "Tomatoe", "Sauce", "Meatballs"]
      },
      {
        name: "Onion Pie",
        ingredients: ["Onion", "Pie Crust"]
      }
    ]
  };

  removeItem = item => {
    const newItems = this.state.items.filter(el => el.name !== item.name);
    this.setState({ items: newItems });
  };

  editItem = item => alert(`${item.name} will be edited`);

  renderItems = () =>
    this.state.items.map(item => (
      <Item
        key={item.name}
        item={item}
        removeItem={this.removeItem}
        editItem={this.editItem}
      />
    ));

  render() {
    return <div className="box">{this.renderItems()}</div>;
  }
}

const Item = props => {
  const { item, removeItem, editItem } = props;
  const handleRemove = () => removeItem(item);
  const handleEdit = () => editItem(item);

  return (
    <div>
      <div className="Recipe-Item-Container" key={props.text}>
        <div className="Recipe-Item">
          <h3>{item.name}</h3>
          <ul>
            {item.ingredients.map(ingredient => (
              <li key={ingredient}>{ingredient}</li>
            ))}
          </ul>
          <div className="buttons-container">
            <button className="edit-button" onClick={handleEdit}>
              Edit
            </button>
            <button className="delete-button" onClick={handleRemove}>
              Delete
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

变化

  • 状态形状:我们不是保存两个数组,而是为每个项目保留一个对象。这个对象有一个nameingredients属性。也许在未来,它可能有一个独特的id对象是灵活的。
  • 我们不是将所有项目都传递给一个Item组件,而是映射父组件中的项目,并且只将一个项目传递给该Item组件。
  • 我们仍然在父级中定义了处理函数。但是,我们没有直接在带有箭头函数的按钮回调中使用它们。因此,它们不会在每次渲染中重新创建。此外,我们不必使用索引将项目传回父项。我们有itemprops本身!您可以看到我们如何处理删除功能:.filter您可以将相同的功能应用于其他功能。.map, .filter,Object.assign或 spread 语法都是很好的工具。只是,避免直接改变你的状态。