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