React,将状态作为道具传递的问题

时间:2021-02-16 09:41:25

标签: reactjs react-native

所以我对 React 世界还是很陌生,我正在尝试解决这个问题,但我不太明白为什么会这样。

所以我想将组件的状态传递给父组件,从父组件传递给子组件,一切看起来都很好,在控制台日志中状态变为低谷,但没有任何变化。我相信有一种方法我需要监听状态变化或子组件中的某些东西,这样它才能工作。如果我在父组件中设置 true,子组件也会为 true,但是如果我在点击时切换它,它会进入低谷,但子组件中没有任何变化。

另外,我知道我的代码现在有点粗糙,稍后会重构它,但现在我正在尝试理解为什么它不起作用。

如果有人能帮助我,我将不胜感激。

这是控制状态的组件..所以状态从 TurnOnBtn 传递到 App,从 App 传递到 TodoList

import "./Todo.css";

class TurnOnBtn extends Component {
  constructor(props) {
    super(props);
    this.state = { display: false };
    this.handleState = this.handleState.bind(this);
  }

  handleState() {
    this.setState({ display: !this.state.display });
    this.props.checkDisplay(this.state.display);
  }

  render() {
    return (
      <button onClick={this.handleState} className="TurnOnBtn">
        <i className="fa fa-power-off"></i>
      </button>
    );
  }
}

export default TurnOnBtn;

父组件应用

import TurnOnBtn from "./TurnOnBtn";
import TheMatrix from "./TheMatrxHasYou";
import TodoList from "./TodoList";
import { Component } from "react";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = { display: true };
    this.checkDisplay = this.checkDisplay.bind(this);
  }

  checkDisplay(newDisplay) {
    this.setState({
      display: newDisplay,
    });
    console.log(this.state);
  }

  render() {
    return (
      <div className="App">
        <TodoList display={this.state.display} />
        <TheMatrix />
        <TurnOnBtn checkDisplay={this.checkDisplay} />
      </div>
    );
  }
}

export default App;

子组件 TodoList

import Todo from "./Todo";
import NewTodoForm from "./NewTodoForm";
import { v4 as uuid } from "uuid";
import "./Todo.css";

class TodoList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      todos: [],
      displayOn: this.props.display,
    };
    this.newTodo = this.newTodo.bind(this);
    this.editTodo = this.editTodo.bind(this);
    this.deleteTodo = this.deleteTodo.bind(this);
  }

  editTodo(id, updatedTask) {
    const updatedTodo = this.state.todos.map((todo) => {
      if (todo.id === id) {
        return { ...todo, todo: updatedTask };
      }
      return todo;
    });
    this.setState({
      todos: updatedTodo,
    });
    console.log(updatedTask);
  }

  deleteTodo(id) {
    this.setState({
      todos: this.state.todos.filter((todo) => todo.id !== id),
    });
  }

  newTodo(newState) {
    this.setState({
      todos: [...this.state.todos, { ...newState }],
    });
  }

  render() {
    return (
      <div
        style={this.state.displayOn ? { opacity: 1 } : { opacity: 0 }}
        className="Todo-screen"
      >
        {" "}
        <div className="TodoList">
          <div className="TodoList-todos">
            {" "}
            {this.state.todos.map((todo) => (
              <Todo
                key={uuid()}
                id={todo.id}
                active={todo.active}
                editTodo={this.editTodo}
                deleteTodo={this.deleteTodo}
                todoItem={todo.todo}
              />
            ))}
          </div>
        </div>{" "}
        <NewTodoForm newTodo={this.newTodo} />
      </div>
    );
  }
}

export default TodoList;

1 个答案:

答案 0 :(得分:0)

这里的错误是在这行代码中:

handleState() {
  this.setState({ display: !this.state.display });
  this.props.checkDisplay(this.state.display);
}

请记住,setState 是一个异步函数,因此当您使用 setState 设置新状态时,this.state 的值不一定会更改。

解决此问题的一种方法是使用 setState 回调,该回调将在状态更改后运行:

handleState() {
  this.setState({ display: !this.state.display }, function() {
    this.props.checkDisplay(this.state.display);
  }); 
}

但是您不需要使用其他状态来将 display 状态保持在 TurnOnBtn 中,因为您可以从父级传递切换回调:

App.js

class App extends Component {
  constructor(props) {
    super(props);
    this.state = { display: true };
    this.toggleDisplay = this.toggleDisplay.bind(this);
  }

  toggleDisplay() {
    this.setState({
      display: !this.state.display,
    });
  }

  render() {
    return (
      <div className="App">
        <TodoList display={this.state.display} />
        <TheMatrix />
        <TurnOnBtn toggleDisplay={this.toggleDisplay} />
      </div>
    );
  }
}

TurnOnBtn.js

class TurnOnBtn extends Component {
  constructor(props) {
    super(props);
    this.handleState = this.handleState.bind(this);
  }

  handleState() {
    this.props.toggleDisplay();
  }

  render() {
    return (
      <button onClick={this.handleState} className="TurnOnBtn">
        <i className="fa fa-power-off"></i>
      </button>
    );
  }
}