如何解决更好地使用useEffect挂钩,因为不需要使用回调
我已经编写了以下React组件,它对依赖项和需要的内容很混乱
useCallback
我的问题是:我对钩子有什么误解,认为我一直需要在哪里使用此useCallback
?
const TagPicker = ({ value,defaultValue,tags,updateTags }) => {
const thisPicker = useRef(null);
const thisInput = useRef(null);
// Managing Tags
const [ selectedTags,setSelectedTags ] = useState(value || defaultValue);
const getIds = useCallback(() => {
let ids = [];
for(let x in selectedTags) {
ids.push(selectedTags[x].id);
}
return ids;
},[ selectedTags ]);
const addTag = useCallback(tag => {
let ids = getIds();
if(!ids.includes(tag.id)) setSelectedTags([ ...selectedTags,tag ]);
},[ selectedTags,getIds ]);
const removeTag = tag => {
let ids = getIds();
if(ids.includes(tag.id)) setSelectedTags([ ...selectedTags].filter(t => (t.id !== tag.id)));
}
// Typed text / Filtered List
const [ text,setText ] = useState('');
const [ filteredList,setFilteredList ] = useState([]);
useEffect(() => {
let ids = getIds();
if(text.length) {
let filteredTags = tags.filter(tag => (!ids.includes(tag.id)));
setOpen(true);
let list = [];
for(let x in filteredTags) {
if(filteredTags[x].title.toLowerCase().includes(text.toLowerCase())) list.push(filteredTags[x]);
}
setFilteredList(list);
} else {
setOpen(false);
setFilteredList([])
}
},text,getIds ]);
useEffect(() => {
updateTags(selectedTags);
},[ updateTags,selectedTags ]);
// Toggling dropdown menu
const [ open,setOpen ] = useState(false);
useEffect(() => {
if(open) getCoordinates(thisPicker);
},[ open ]);
// Handling Coordinates
const [ coords,setCoords ] = useState(null);
const getCoordinates = ({ current }) => {
if(current) {
const rect = current.getBoundingClientRect();
setCoords({
left: rect.x,top: rect.y + window.scrollY + 40
});
}
}
useEffect(() => {
window.addEventListener('resize',() => getCoordinates(thisPicker));
return () => window.removeEventListener('resize',() => getCoordinates(thisPicker));
},[]);
// Handle Enter
const handleEnter = useCallback(e => {
if(e.keyCode === 13 && text) {
if(filteredList.length) addTag(filteredList[0]);
else addTag({
id: Math.random(),title: text
});
setText('');
setOpen(false);
}
},[ addTag,filteredList ]);
useEffect(() => {
let el = thisInput.current;
el.addEventListener('keyup',e => handleEnter(e));
return () => el.removeEventListener('keyup',e => handleEnter(e));
},[ handleEnter ]);
return(
<div className='tag-picker' ref={thisPicker}>
<input type='text' value={text} onChange={e => setText(e.target.value)} ref={thisInput} />
<div className='selected-tags'>
{ selectedTags.map(tag => (
<Tag tag={tag} key={tag.id} removeTag={removeTag} />
)) }
</div>
{ open ?
<Portal>
<List text={text} items={filteredList} onSelect={addTag} setOpen={setOpen} coords={coords} />
</Portal>
: null }
</div>
);
};
解决方法
您的第一个useEffect
存在一些问题。它具有一个额外的依赖项selectedTags
。
如果您不使用useCallback
来包装回调,则效果的确取决于selectedTags
。如果您使用useCallback
,则效果仅取决于回调。
实际上,它们的含义是相同的。如果useCallback
的依存关系发生更改,则回调也将重新计算。因此,selectedTags
的更改将触发回调(您的getIds
)的更改,并触发以下效果:如果没有useCallback
,则将依赖项直接放在useEffect
的依赖项数组中因此它们的更改会直接触发效果。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。