reactjs - 如何在 React 函數組件中顯示/隱藏加載指示器、訊息提示或其他短暫元件
將旋轉器、訊息提示條等呈現在單獨的 DOM 元素中,而不是添加到主要應用組件樹中,是否更好?在 React 類組件中,非常容易獲取類組件的方法引用來顯示/隱藏旋轉器。但在新的 React Hooks 函數組件中,就不那麼容易了。如果我將旋轉器放在主組件樹中,我可以使用新的 “useContext” 鉤子來顯示/隱藏旋轉器嗎?
以下是一個使用 Material-UI 的 React Hooks 全局加載動畫,它能運作但非常不夠優雅。如何能使它更優雅?
namespace Spinner {
'use strict';
export let show: any; // Show method ref.
export let hide: any; // Hide method ref.
export function Render() {
const [visible, setVisible] = React.useState(false); //Set refresh method.
function showIt() {
setVisible(true); // Show spinner.
}
function hideIt() {
setVisible(false); // Hide spinner.
}
const styles: any = createStyles({
col1Container: { display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column' },
});
return (
<div>
{visible && <div style={styles.col1Container}>
<CircularProgress key={Util.uid()}
color='secondary'
size={30}
thickness={3.6}
/>
</div>}
<SetSpinnerRefs showRef={showIt} hideRef={hideIt} />
</div>
); // end return.
} // end function.
const mounted: boolean = true;
interface iProps {
showRef();
hideRef();
}
function SetSpinnerRefs(props: iProps) {
// ComponentDidMount.
React.useEffect(() => {
Spinner.show = props.showRef;
Spinner.hide = props.hideRef;
}, [mounted]);
return (<span />);
}
} // end module.
答案#1
這個問題類似於這個,而對旋轉器的解決方案將與模態窗口的解決方案相同。React hooks 不會改變它的工作方式,但可以使其更簡潔。
在組件層級中應該只有一個加載器實例:
const SpinnerContext = React.createContext();
const SpinnerContainer = props => {
const [visible, setVisible] = React.useState(false);
const spinner = useMemo(() => ({
show: () => setVisible(true),
hide: () => setVisible(false),
}), []);
render() {
return <>
{visible && <Spinner />}
<SpinnerContext.Provider value={spinner}>
{props.children}
</SpinnerContext.Provider>
</>;
}
}
這是隨著上下文傳遞的:
const ComponentThatUsesSpinner = props => {
const spinner = useContext(SpinnerContext);
...
spinner.hide();
...
}
<SpinnerContainer>
...
<ComponentThatUsesSpinner />
...
</SpinnerContainer>
答案#2
在 React 類別元件中,非常容易取得類別元件方法的參考來顯示/隱藏加載指示器
你可以繼續使用類別元件。它們不會消失 🌹
不太好的方式
在我看來,使用類方法來顯示和隱藏加載動畫實際上是很差的做法。假設你的 API 看起來像
<Spinner {ref=>this.something=ref}/>
而你使用
this.something.show(); // or .hide
更好的方法
<Spinner shown={state.shown}/>
現在你可以更改 state.shown,而不是儲存引用並使用 show/hide。
