Реагирует, проблема с передачей состояния в качестве реквизита

#reactjs #react-native

#reactjs #реагировать -родной

Вопрос:

Итак, я совсем новичок в мире 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;
 

список дочерних компонентов

 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:

Ошибка здесь в этих строках кодов:

 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>
    );
  }
}