使用引用从父级更改子级组件的状态

时间:2019-06-07 23:01:52

标签: javascript reactjs state

我有一个TaskList。我正在尝试显示一个子组件TaskEdit(该任务的编辑框),位于按钮onClick下方几个组件。

TaskEdit具有状态变量hidden,默认情况下设置为true。如何从子组件内部更改子组件内部的状态?

反应文档中提到了forwardRef()函数以引用子组件,但是到目前为止,我还没有运气。

这是我的代码:

import TaskEdit from '../TaskEdit';

class TasksBase extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      loading: false,
      tasks: [],
    };
    this.markTaskAsCompleted = this.markTaskAsCompleted.bind(this);
    this.deleteTask = this.deleteTask.bind(this);
    this.incrementDate = this.incrementDate.bind(this);
    this.toggleTaskEdit = this.toggleTaskEdit.bind(this);
  }

  componentDidMount() {
    this.onListenForTasks();
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  render() {
    const { tasks, loading } = this.state;
    return (
      <div>
        {loading && <div>Loading ...</div>}
        {tasks ? (
          <TaskList tasks={tasks}
                    handleToggleEdit={this.toggleTaskEdit}
                    handleMarkCompleted={this.markTaskAsCompleted}
                    handleDeleteTask={this.deleteTask}
                    taskEditElement={this.editTaskElement}
          />
        ):(
          <div>There are no tasks ...</div>
        )}
      </div>
    );
  }

  onListenForTasks() {
    this.setState({ loading: true });

    this.unsubscribe = this.props.firebase
      .tasks()
      .orderBy('importance', 'desc')
      .orderBy('urgency', 'desc')
      .orderBy('created', 'desc')
      .onSnapshot(snapshot => {
        if (snapshot.size) {
          let tasks = [];
          snapshot.forEach(doc =>
            tasks.push({ ...doc.data(), uid: doc.id }),
          );
          this.setState({
            tasks: tasks,
            loading: false
          });
        } else {
          this.setState({ tasks: null, loading: false });
        }
    });
  }

  markTaskAsCompleted(task){
    // Some code
  }

  deleteTask(id){
    // Some code
  }

  toggleEditTask(){
    this.editTaskElement.current.toggle();
  }
}


const Tasks = withFirebase(TasksBase);

const TaskList = ({ tasks, handleToggleEdit, handleMarkCompleted, handleDeleteTask }) => (
  <ul className="tasks">
    {tasks.map( task => (
      <Task key={task.uid}
            task={task}
            handleToggleEdit={handleToggleEdit}
            handleMarkCompleted={handleMarkCompleted}
            handleDeleteTask={handleDeleteTask}
      />
    ))}
  </ul>
);

const Task = ({ task, handleToggleEdit, handleMarkCompleted, handleDeleteTask}) => (
  (!task.completed && !task.obsolete && !task.waitingForDependencies) && (!task.start || task.start.toMillis() <= Date.now()) &&
    <li className="task">
      <strong>{task.userId}</strong> {task.name}
      { task.estimate &&
        <span>{task.estimate.amount + task.estimate.unit}</span>
      }
      <div className="icons">
        <FontAwesomeIcon icon="edit" onClick={() => handleToggleEdit(task)} />
        <FontAwesomeIcon icon="check-circle" onClick={() => handleMarkCompleted(task)} />
        <FontAwesomeIcon icon="times-circle" onClick={() => handleDeleteTask(task.uid)}/>
      </div>
      <TaskEdit task={task} />
    </li>
);

const condition = authUser => !!authUser;

export default compose(
  withEmailVerification,
  withAuthorization(condition),
)(Tasks);

TaskEdit:

import React, { Component } from 'react';
import { withFirebase } from '../Firebase';

const INITIAL_STATE = {
    hidden: true,
};

class TaskEditBase extends Component {

    constructor(props) {
    super(props);
    this.state = { ...INITIAL_STATE };
    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;
    console.log("name " + name);
    console.log("value " + value);

    this.setState({
      [name]: value
    });
  }

  toggle(){
    this.setState({
        hidden: !this.prevState.hidden
    })
  }

  onSumbitTaskEdit = (event) => {
    event.preventDefault();
  };

  render(){

    return(
        !this.state.hidden &&
        <div className="task-edit">
          <form onSubmit={this.onSumbitTaskEdit}>
            <div>A bunch of inputs</div>
            <input type="submit" value="Edit"/>
          </form>
        </div>
    )
  }

}

const TaskEdit = withFirebase(TaskEditBase);

export default TaskEdit;

0 个答案:

没有答案