如何使用 usestate 和 setstate 而不是 this.setState 使用 react 和 typescript?
Posted
技术标签:
【中文标题】如何使用 usestate 和 setstate 而不是 this.setState 使用 react 和 typescript?【英文标题】:How to use usestate and setstate instead of this.setState using react and 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 一起使用。谢谢。
【参考方案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"以上是关于如何使用 usestate 和 setstate 而不是 this.setState 使用 react 和 typescript?的主要内容,如果未能解决你的问题,请参考以下文章
使用立即需要该状态进行 API 调用的 useState 挂钩时,如何等待 setState 调用完成?
如何避免未使用的 setState 函数?可以在没有 setter 的情况下创建 React useState 吗?
如何使用我的反应应用程序中的 useState 钩子给出的 setState 方法增加状态对象的选定索引的计数