【问题标题】:How to use usestate and setstate instead of this.setState using react and typescript?如何使用 usestate 和 setstate 而不是 this.setState 使用 react 和 typescript?
【发布时间】:2020-09-16 18:38:06
【问题描述】:

我想使用 react 和 typescript 实现一个 DragAndDrop 组件,而且我是使用 react redux 的新手。

下面是 DragAndDrop 组件的样子,

class DragAndDrop extends Component {
    constructor(props) {
        super(props);
        this.state = {
            dragging: false,
        }; 
    }

    componentDidMount() {
        this.drag_counter = 0;
        this.enable_drag_event_listeners();
    }

    componentWillUnmount() {
        this.disable_drag_event_listeners();
    }

    enable_drag_event_listeners = () => {
        document.addEventListener('dragenter', this.handle_drag_in);
        document.addEventListener('dragleave', this.handle_drag_out);
        document.addEventListener('dragover', this.handle_drag);
        document.addEventListener('drop', this.handle_drop);
    }

    disable_drag_event_listeners = () => {
        document.removeEventListener('dragenter', this.handle_drag_in);
        document.removeEventListener('dragleave', this.handle_drag_out);
        document.removeEventListener('dragover', this.handle_drag);
        document.removeEventListener('drop', this.handle_drop);
    }

    handle_drag = (e) => {
        if (!this.props.loading) {
            e.preventDefault();
            e.stopPropagation();
        }
    }

    handle_drag_in = (e) => {
        if (!this.props.loading) {
            e.preventDefault();
            e.stopPropagation();
            this.drag_counter++;
            if (e.dataTransfer.files) {
                this.setState({dragging: true});
            }
        }
    }

    handle_drag_out = (e) => {
        if (!this.props.loading) {
            e.preventDefault();
            e.stopPropagation();
            this.drag_counter--;
            if (this.drag_counter === 0) {
                this.setState({dragging: false});
            }
        }
    }

    handle_drop = (e) => {
        if (!this.props.loading) {
            e.preventDefault();
            e.stopPropagation();
            this.setState({dragging: false});
            if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
                this.props.handle_drop(e);
                e.dataTransfer.clearData();
                this.drag_counter = 0;
            }
        }
    }

    render() {
        return (
            <div>
                {this.state.dragging &&
                    <div>
                        <div className="drop_zone">
                            <div className="drop_zone_overlay"/>
                            <div className="drop_zone_text">
                            <div>Drop your files here</div>
                        </div>
                    </div>
                }
                {this.props.children}
            </div>
        )
    }
}

从上面的代码可以看出,我使用了this.state和this.setState、componentdidmount、componentdidupdate和componentwillunmount。

我想用react redux usestate,setstate之类的东西。

如何更改上述代码以使用 usestate 和 setstate,以及如何实现 componentdidmount、componentdidupdate、componentwillunmount 钩子。

我尝试了什么?

function DragAndDrop() {
    const [isdragging, setIsDragging] = React.useState(false);
    handle_drag = (e) => {
        if (!this.props.loading) {
            e.preventDefault();
            e.stopPropagation();
        }
    }

    handle_drag_in = (e) => {
        if (!this.props.loading) {
            e.preventDefault();
            e.stopPropagation();
            this.drag_counter++; //how do i set this with react redux and also this is not a class

            if (e.dataTransfer.files) {
                setIsDragging(true);
            } 
        }
    }

    handle_drag_out = (e) => {
        if (!this.props.loading) {
            e.preventDefault();
            e.stopPropagation();
            this.drag_counter--; // how to keep track of this counter
            if (this.drag_counter === 0) {
                setIsDragging(false);
            }  
        }
    }

    handle_drop = (e) => {
        if (!this.props.loading) {
            e.preventDefault();
            e.stopPropagation();
            setIsDragging(false);
            if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
                this.props.handle_drop(e);
                e.dataTransfer.clearData();
                this.drag_counter = 0; //how to keep track of this
            }
        }
    }

    render() {
        return (
            <div>
                {isdragging &&
                    <div>
                        <div className="drop_zone">
                            <div className="drop_zone_overlay"/>
                            <div className="drop_zone_text">
                                <div>Drop files here</div>
                            </div>
                        </div>
                    </div>
                }
                {this.props.children}
            </div>
        )
    }
}

有人可以帮我解决这个问题吗?谢谢。 react redux中如何考虑componentdidmount、componentdidupdate、componentwillunmount。

谢谢。

【问题讨论】:

  • 你不能在函数组件中使用this
  • 我认为你应该先阅读reactjs.org/docs/hooks-intro.html
  • 好的,那么我如何修改这个组件以与 react、typescript 和 redux 一起使用。谢谢。

标签: reactjs typescript


【解决方案1】:

const DragAndDrop: React.FC<any> = (props) => {
  const [dragging, setDragging] = React.useState(false);
  const [drag_counter, setDrag_counter] = React.useState(0);
  React.useEffect(() => {
    // componentDidMount()
    setDrag_counter(0);
    enable_drag_event_listeners();
    return () => {
      // componentWillUnmount()
      disable_drag_event_listeners();
    }
  }, []);

  function enable_drag_event_listeners() {
    document.addEventListener('dragenter', handle_drag_in);
    document.addEventListener('dragleave', handle_drag_out);
    document.addEventListener('dragover', handle_drag);
    document.addEventListener('drop', handle_drop);
  }

  function disable_drag_event_listeners() {
    document.removeEventListener('dragenter', handle_drag_in);
    document.removeEventListener('dragleave', handle_drag_out);
    document.removeEventListener('dragover', handle_drag);
    document.removeEventListener('drop', handle_drop);
  }

  function handle_drag(e) {
    if (!props.loading) {
      e.preventDefault();
      e.stopPropagation();
    }
  }

  function handle_drag_in(e) {
    if (!props.loading) {
      e.preventDefault();
      e.stopPropagation();
      setDrag_counter((prev)=>prev+1);
      if (e.dataTransfer.files) {
        setDragging(true);
      }
    }
  }

  function handle_drag_out(e) {
    if (!props.loading) {
      e.preventDefault();
      e.stopPropagation();
      setDrag_counter((prev)=>prev-1);
      if (drag_counter === 0) {
        setDragging(false);
      }
    }
  }

  function handle_drop(e) {
    if (!props.loading) {
      e.preventDefault();
      e.stopPropagation();
      setDragging(false);
      if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
        props.handle_drop(e);
        e.dataTransfer.clearData();
        setDrag_counter(0);
      }
    }
  }
  return ( 
    <div>
    {dragging &&
      <div>
      <div className = "drop_zone" >
        <div className = "drop_zone_overlay" / >
        <div className = "drop_zone_text" >
          <div> Drop your files here </div> 
        </div> 
      </div>
    } 
    {
      props.children
    } 
    </div>
  )

}

【讨论】:

  • 我在定义 enable 和 disable_drag_event_listeners 的地方出现错误,如下所示“enable_drag_event_listeners 函数使 useEffect 挂钩的依赖关系在每次渲染时都发生变化。将其移动到 useEffect 回调中。或者,包装enable_drag_event_listeners 进入它自己的 useCallback hook"
猜你喜欢
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 2020-07-02
  • 2020-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多