首頁 >web前端 >js教程 >上下文、Redux 還是組合?

上下文、Redux 還是組合?

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-12-19 11:28:09604瀏覽

這篇文章最初發佈於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,並沒有真正使用它。

Context, Redux or Composition?

這是 React 中的一個經典 prop 鑽孔 問題。

有趣的是,面試官要求透過 React Context API 來解決問題
或使用 Redux。

透過 React 上下文解決

使用 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 傳遞給深度嵌套的子元件。這個解決方案
有效。

Context, Redux or Composition?

透過 Redux 解決

所以,如果我們要走經典的 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。我們也獲得其他好處,例如
作為

  • 將來,如果我們在 Dashboard 中引入任何狀態並對其進行操作,我們的 DashboardNav 永遠不會重新渲染。
  • 透過提供道具僅提供給所需的組件,我們擁有良好的可見性 用戶的所有消費者,無需在組件(文件)之間導航 尋找他們。

這種模式並不新鮮,並且已經在 React 社群中討論過。一個這樣好的演練是在 React 中使用組合來避免「Prop Drilling」

結論

但是,我收到面試官的回饋,是這樣的

受訪者沒有正確理解問題,無法提供預期的解決方案。

我猜原因要不是面試官沒有意識到這種模式,就是我選擇以一種沒有被要求的方式解決問題。

話雖如此,我現在有動力寫更多關於 React 中有趣的模式,希望它能吸引更廣泛的受眾。

分享這篇文章讓我知道您的想法。


參考文獻

  • Codesandbox 解決方案
  • 使用上下文之前 - React 文件
  • 在 React 中使用組合來避免「Prop Drilling」
  • 部落格答案:React 渲染行為(大部分)完整指南
  • 部落格回答:為什麼 React Context 不是「狀態管理」工具(以及為什麼它不取代 Redux)

以上是上下文、Redux 還是組合?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn