這篇文章最初發佈於2023年2月23日@我的部落格頁面
我是受到最近科技公司裁員影響的開發人員之一。所以,我開始用 React 面試前端職位。
在其中一家公司,我在反應中遇到了一個經典的道具鑽孔問題,
並被要求解決它。為了簡單起見,給出的問題就像
這個:
export default function App() { const [user, setUser] = React.useState(null); const handleLogin = () => setUser(userDetails); return ( <div className="App"> Company Logo <div> {user ? ( <Dashboard user={user} /> ) : ( <button onClick={handleLogin}>Login</button> )} </div> </div> ); } function Dashboard({ user }) { return ( <div> <DashboardNav user={user} /> </div> ); } function DashboardNav({ user }) { return ( <div> <WelcomeUser user={user} /> <UserRole user={user} /> </div> ); } function WelcomeUser({ user }) { return <div>Welcome {user.name}</div>; } function UserRole({ user }) { return <div>Role {user.role}</div>; }
如您所觀察到的,我們將 user 屬性從 App 元件傳遞到
子組件WelcomeUser 和UserRole。中間元件 Dashboard 和 DashboardNav 只是轉發 props,並沒有真正使用它。
這是 React 中的一個經典 prop 鑽孔 問題。
有趣的是,面試官要求透過 React Context API 來解決問題
或使用 Redux。
使用 context API 來解決這個問題,程式碼如下。
const UserContext = React.createContext(undefined); export default function App() { const [user, setUser] = React.useState(null); const handleLogin = () => setUser(userDetails); return ( <div className="App"> Company Logo: Context <div> {user ? ( <UserContext.Provider value={user}> <Dashboard /> </UserContext.Provider> ) : ( <button onClick={handleLogin}>Login</button> )} </div> </div> ); } function Dashboard() { return ( <div> <DashboardNav /> </div> ); } function DashboardNav() { return ( <div> <WelcomeUser /> <UserRole /> </div> ); } function WelcomeUser() { const user = React.useContext(UserContext); return <div>Welcome {user.name}</div>; } function UserRole() { const user = React.useContext(UserContext); return <div>Role {user.role}</div>; }
我們正在建立 UserContext 並使用 Provider 包裝儀表板,以便
我們可以將我們想要的 props 傳遞給深度嵌套的子元件。這個解決方案
有效。
所以,如果我們要走經典的 redux 路線,我們需要建立一個類似的
使用單一全域儲存來建構和包裝所有內容,其中包含使用者
目的。
解決方案程式碼將包含大量樣板文件,因為我們使用 redux 來
解決一個簡單的問題。
我只是給了下面程式碼的要點,但如果你真的想探索完整的
程式碼,在這裡:用 redux 解決。
export default function App() { return ( <Provider store={store}> <ReduxConnectedApp /> </Provider> ); } function ReduxApp({ user, setUser }) { const handleLogin = () => setUser(userDetails); return ( <div className="App"> Company Logo: Redux <div> {user ? <Dashboard /> : <button onClick={handleLogin}>Login</button>} </div> </div> ); } function Dashboard() { return ( <div> <DashboardNav /> </div> ); } function DashboardNav() { return ( <div> <ConnectedWelcomeUser /> <ConnectedUserRole /> </div> ); } function WelcomeUser({ user }) { return <div>Welcome {user.name}</div>; } const mapStateToPropsWelcomeUser = (state) => ({ user: state }); const ConnectedWelcomeUser = connect(mapStateToPropsWelcomeUser)(WelcomeUser); function UserRole({ user }) { return <div>Role {user.role}</div>; } const mapStateToPropsUserRole = (state) => ({ user: state }); const ConnectedUserRole = connect(mapStateToPropsUserRole)(UserRole);
我們已經連接了需要存取全域狀態的元件
儲存在redux中。
閱讀了有關反應組合的內容後,我透過製作解決了問題
使用 Children 道具,看起來像這樣
export default function AppSolution() { const [user, setUser] = React.useState(null); const handleLogin = () => setUser(userDetails); return ( <div className="App"> Company Logo <div> {user ? ( <Dashboard> <DashboardNav> <WelcomeUser user={user} /> <UserRole user={user} /> </DashboardNav> </Dashboard> ) : ( <button onClick={handleLogin}>Login</button> )} </div> </div> ); } function Dashboard({ children }) { return <div>{children}</div>; } function DashboardNav({ children }) { return <div>{children}</div>; } function WelcomeUser({ user }) { return <div>Welcome {user.name}</div>; } function UserRole({ user }) { return <div>Role {user.role}</div>; }
如果你仔細想想,這是解決這個問題的簡單方法,無需介紹
任何複雜性,如 createContext 或 react-redux。我們也獲得其他好處,例如
作為
這種模式並不新鮮,並且已經在 React 社群中討論過。一個這樣好的演練是在 React 中使用組合來避免「Prop Drilling」
但是,我收到面試官的回饋,是這樣的
受訪者沒有正確理解問題,無法提供預期的解決方案。
我猜原因要不是面試官沒有意識到這種模式,就是我選擇以一種沒有被要求的方式解決問題。
話雖如此,我現在有動力寫更多關於 React 中有趣的模式,希望它能吸引更廣泛的受眾。
分享這篇文章讓我知道您的想法。
參考文獻
以上是上下文、Redux 還是組合?的詳細內容。更多資訊請關注PHP中文網其他相關文章!