反应中类基组件和功能组件的问题

时间:2021-07-21 14:00:01

标签: javascript reactjs

我有一个简单的应用程序来反应,当我的 app.js 是一个类组件时,一切都很好,但是当我将它更改为功能组件时发生错误 = todos.filter is not a function

我的文件:Todo.js(函数式) --> TodoList.js(函数式) --> app.js(函数式)

function TodoList(props) {
  const [statusDone, setDone] = useState(false);

  let { todos } = props;
  console.log(todos);

  let filterTodos = todos.filter((item) => item.done === statusDone);

  return (
    <>
      <nav className="col-6 mb-3">
        <div className="nav nav-tabs" id="nav-tab" role="tablist">
          <a
            className={`nav-item nav-link font-weight-bold ${
              !statusDone ? "active" : ""
            }`}
            id="nav-home-tab"
            onClick={() => setDone(false)}
          >
            undone{" "}
            <span className="badge badge-secondary">
              {todos.filter((item) => item.done === false).length}
            </span>
          </a>
          <a
            className={`nav-item nav-link font-weight-bold ${
              statusDone ? "active" : ""
            }`}
            id="nav-profile-tab"
            onClick={() => setDone(true)}
          >
            done{" "}
            <span className="badge badge-success">
              {todos.filter((item) => item.done === true).length}
            </span>
          </a>
        </div>
      </nav>
      {filterTodos.length === 0 ? (
        <p>there isn`t any todos</p>
      ) : (
        filterTodos.map((item) => (
          <Todo
            key={item.key}
            item={item}
            delete={props.delete}
            done={props.done}
            edit={props.edit}
          />
        ))
      )}
    </>
  );
}
<块引用>

主应用类

function App() {
  const [todos, settodos] = useState([]);

  let addTo = (text) => {
    settodos((prevState) => {
      return {
        todos: [prevState.todos, { key: Date.now(), done: false, text }],
      };
    });
  };

  return (
    <div className="App">
      <main>
        <section className="jumbotron">
          <div className="container d-flex flex-column align-items-center">
            <h1 className="jumbotron-heading">Welcome!</h1>
            <p className="lead text-muted">
              To get started, add some items to your list:
            </p>
            <FormAddTodo add={addTo} />
          </div>
        </section>
        <div className="todosList">
          <div className="container">
            <div className="d-flex flex-column align-items-center ">
              <TodoList
                todos={todos}
                // delete={this.deleteTodo.bind(this)}
                // done={this.toggleTodo.bind(this)}
                // edit={this.editTodo.bind(this)}
              />
            </div>
          </div>
        </div>
      </main>
    </div>
  );
}
<块引用>

我试过了

let filterTodos =Object.values(todos).filter(item => item.done === statusDone)

错误已修复,但我的代码无法正常工作

我希望你明白我说的话:)

<块引用>

此功能组件用于添加待办事项

function FormAddTodo(props) {
  const [text, setText] = useState("");

  let formHandler = (e) => {
    e.preventDefault();
    props.add(text);
    setText("");
  };

  let inputHandler = (e) => setText(e.target.value);

  return (
    <form className="form-inline mb-5" onSubmit={formHandler}>
      <div className="row form-group">
        <div className="col-8">
          <input
            type="text"
            className=" form-control mx-sm-3"
            placeholder="i want to do ..."
            value={text}
            onChange={inputHandler}
          />
        </div>
        <div className="col-4">
          <button type="submit" className="  btn btn-primary">
            add
          </button>
        </div>
      </div>
    </form>
  );
}

2 个答案:

答案 0 :(得分:1)

问题出在 addTo 函数上。您不是将元素添加到 todos 数组,而是将 todos 设置为一个对象,其键名为 todos,其中包含一个数组。尝试以这种方式修改 addTo 函数:

const addTo = (text) => {
    let newElement = { key: Date.now(), done: false, text: text };
    settodos(prevState => [...prevState, newElement]);
};

答案 1 :(得分:1)

这里有一个错误:

function App() {
  const [todos, settodos] = useState([]);

  let addTo = (text) => {
    settodos((prevState) => {
      return {
        todos: [prevState.todos, { key: Date.now(), done: false, text }],
      };
    });
  };

您在 settodos 中的变异函数可以尝试将 prevState.todos 与新的待办事项连接起来。

实际上使用 useState setter,您可以直接获取值:

settodos(currentTodos => ...)

然后返回你想要的值(你返回一个对象而不是一个数组)

此外,如果您想连接两个数组,请使用扩展运算符:

const newArray = [...someArray, newValue];

总而言之,这是一段代码的固定版本:

function App() {
  const [todos, settodos] = useState([]);

  let addTo = (text) => {
    settodos((prevTodos) => [
      ...prevTodos,
      { key: Date.now(), done: false, text }
    ]);
  };