我正在尝试转换class component to functional component
。但出现此错误
功能组件不能具有引用。您是要使用React.forwardRef()吗?
使用class component
https://codesandbox.io/s/highlight-search-results-wqtlm?file=/src/components/Search/List.js
现在,我将list
类组件更改为功能组件
https://codesandbox.io/s/funny-bird-dkfpi?file=/src/components/List.js
我的代码中断并给我下面的错误
功能组件不能具有引用。您是要使用React.forwardRef()吗?
请建议如何解决此错误
import React, { useEffect, useRef, useState} from 'react';
import User from './User';
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
const List = ({users})=>{
const [focusedUser, setFocusedUser] = useState(-1);
const [scrollIntoView, setScrollIntoView] = useState(false);
const userRef = useRef();
const prev = usePrevious({focusedUser});
useEffect(()=>{
if (
focusedUser !== prev.focusedUser &&
scrollIntoView
) {
ensureFocusedItemVisible();
}
},[focusedUser])
const ensureFocusedItemVisible =()=> {
userRef.current &&
userRef.current.scrollIntoView({
behaviour: 'smooth',
block: 'center'
});
}
const handleKeyPress = e => {
// scroll into view only on keyboard navigation
setScrollIntoView( true );
// up arrow
if (e.keyCode === 38) {
const fu = focusedUser <= 0 ? 0 : focusedUser - 1;
setFocusedUser(fu);
}
// down arrow
if (e.keyCode === 40) {
const currentFocus = focusedUser;
// if down key is pressed multiple times on last list item, keep last item highlighted
const fu =
currentFocus >= users.length - 1
? users.length - 1
: currentFocus + 1;
setFocusedUser(fu);
}
};
const handleMouseEvent = id => {
userRef.current && userRef.current.focus();
setScrollIntoView(false);
setFocusedUser(parseInt(id))
};
const listElements = users.map((user, index) => {
const focused = index === focusedUser;
return (
<User
divId={index}
data={user}
focused={focused}
ref={focused && userRef}
handleKeyPress={handleKeyPress}
handleMouseEvent={handleMouseEvent}
/>
);
});
return <div className="result-list">{listElements}</div>;
}
export default List;
答案 0 :(得分:0)
您实际上有2个错误。
第一个在这里:
ref={focused && this.userRef}
第二个在这里:
const prev = usePrevious({ focusedUser });
useEffect(() => {
if (focusedUser !== prev.focusedUser && scrollIntoView) {
ensureFocusedItemVisible();
}
}, [focusedUser]);
这是注释中带解释的修复程序:
import React, { useEffect, useRef, useState } from "react";
import User from "./User";
const List = ({ users }) => {
const [focusedUser, setFocusedUser] = useState(-1);
const [scrollIntoView, setScrollIntoView] = useState(false);
const userRef = useRef();
// You don't need to keep track of the previous value.
// useEffect will be called on first render and whenever one of the values in the dependencies array changes
// So it will run whenever the focusedUser changes
useEffect(() => {
if (scrollIntoView) {
ensureFocusedItemVisible();
}
}, [focusedUser, scrollIntoView]);
const ensureFocusedItemVisible = () => {
userRef.current &&
userRef.current.scrollIntoView({
behaviour: "smooth",
block: "center"
});
};
const handleKeyPress = e => {
// scroll into view only on keyboard navigation
setScrollIntoView(true);
// up arrow
if (e.keyCode === 38) {
const fu = focusedUser <= 0 ? 0 : focusedUser - 1;
setFocusedUser(fu);
}
// down arrow
if (e.keyCode === 40) {
const currentFocus = focusedUser;
// if down key is pressed multiple times on last list item, keep last item highlighted
const fu =
currentFocus >= users.length - 1 ? users.length - 1 : currentFocus + 1;
setFocusedUser(fu);
}
};
const handleMouseEvent = id => {
userRef.current && userRef.current.focus();
setScrollIntoView(false);
setFocusedUser(parseInt(id));
};
const listElements = users.map((user, index) => {
const focused = index === focusedUser;
return (
<User
key={index}
divId={index}
data={user}
focused={focused}
// if it isn't focused pass null
// the ref should be a function or a ref object or null
ref={focused ? userRef : null}
handleKeyPress={handleKeyPress}
handleMouseEvent={handleMouseEvent}
/>
);
});
return <div className="result-list">{listElements}</div>;
};
export default List;