Wie kann ich diese Klassenbasiskomponente höherer Ordnung in eine Funktionskomponente umwandeln?
Lesezeit: 10 Minuten
Mohammed Amir Ansari
Ich habe in meiner folgenden Reaktions-App bereits ein HOC erstellt Das, und es funktioniert gut. Allerdings habe ich mich gefragt, ob es eine Möglichkeit gibt, ein HOC als Funktionskomponente (mit oder ohne Status) zu erstellen? da es sich bei dem gegebenen Beispiel um eine klassenbasierte Komponente handelt.
Habe versucht, das Gleiche über das Internet zu finden, konnte aber nichts finden. Ich bin mir nicht sicher, ob das überhaupt möglich ist?? Oder das Richtige überhaupt??
Jeder Hinweis wird geschätzt 🙂
Ich stimme Siraj zu, streng genommen ist das Beispiel in der akzeptierten Antwort kein echter HOC. Das Unterscheidungsmerkmal eines HOC ist, dass es gibt eine Komponente zurückwährend die PrivateRoute Komponente in der akzeptierten Antwort Ist eine Komponente selbst. Obwohl es also ganz gut erreicht, was es sich vorgenommen hat, halte ich es nicht für ein großartiges Beispiel für ein HOC.
In der Welt der funktionalen Komponenten würde das einfachste HOC so aussehen:
Berufung withNothing gibt eine andere Komponente zurück (keine Instanz, das ist der Hauptunterschied), die dann wie eine reguläre Komponente verwendet werden kann:
Eine Möglichkeit, dies zu nutzen, besteht darin, Ad-hoc zu verwenden (kein Wortspiel beabsichtigt). Lol) Kontextanbieter.
Nehmen wir an, meine Anwendung verfügt über mehrere Punkte, an denen sich ein Benutzer anmelden kann. Ich möchte die Anmeldelogik (API-Aufrufe und Erfolgs-/Fehlermeldungen) nicht über alle diese Punkte hinweg kopieren, daher hätte ich gerne eine wiederverwendbare <Login /> Komponente. Allerdings unterscheiden sich in meinem Fall alle diese Anmeldepunkte optisch deutlich, sodass eine wiederverwendbare Komponente keine Option ist. Was ich brauche, ist ein wiederverwendbares <WithLogin /> Komponente, die ihren untergeordneten Elementen alle notwendigen Funktionen zur Verfügung stellen würde – den API-Aufruf und Erfolgs-/Fehlermeldungen. Hier ist eine Möglichkeit, dies zu tun:
// This context will only hold the `login` method.
// Calling this method will invoke all the required logic.
const LoginContext = React.createContext();
LoginContext.displayName = "Login";
// This "HOC" (not a true HOC yet) should take care of
// all the reusable logic - API calls and messages.
// This will allow me to pass different layouts as children.
const WithLogin = ({ children }) => {
const [popup, setPopup] = useState(null);
const doLogin = useCallback(
(email, password) =>
callLoginAPI(email, password).then(
() => {
setPopup({
message: "Success"
});
},
() => {
setPopup({
error: true,
message: "Failure"
});
}
),
[setPopup]
);
return (
<LoginContext.Provider value={doLogin}>
{children}
{popup ? (
<Modal
error={popup.error}
message={popup.message}
onClose={() => setPopup(null)}
/>
) : null}
</LoginContext.Provider>
);
};
// This is my main component. It is very neat and simple
// because all the technical bits are inside WithLogin.
const MyComponent = () => {
const login = useContext(LoginContext);
const doLogin = useCallback(() => {
login("[email protected]", "password");
}, [login]);
return (
<WithLogin>
<button type="button" onClick={doLogin}>
Login!
</button>
</WithLogin>
);
};
Leider funktioniert das nicht, weil LoginContext.Provider wird instanziiert innenMyComponentund so useContext(LoginContext) gibt nichts zurück.
HOC zur Rettung! Was wäre, wenn ich einen kleinen Mittelsmann hinzufügen würde:
Bumm! MyComponentWithLogin wird jetzt wie erwartet funktionieren.
Das ist vielleicht nicht die beste Herangehensweise an diese besondere Situation, aber ich mag es irgendwie.
Und ja, es ist wirklich nur ein zusätzlicher Funktionsaufruf, mehr nicht! Laut offiziellem Leitfaden:
HOCs sind per se nicht Teil der React-API. Sie sind ein Muster, das sich aus der kompositorischen Natur von React ergibt.
Abgesehen von der ursprünglichen Frage nach einem HOC frage ich mich, ob es noch etwas gibt falsch wobei die akzeptierte Antwort kein echtes HOC, sondern eine Wrapper-Komponente ist?
– Honinbo Shusaku
26. Okt. 2021 um 11:21 Uhr
@Netero Ihre Frage verwirrt mich: ]Der Code in der akzeptierten Antwort ist gültig, er funktioniert und ich vermute, dass das Umbrechen in React weitaus häufiger vorkommt als das HOC-Muster (Zitat erforderlich). Als solches ist es so kein schlechter Codees ist nur ein falsche Antwort. Beim Wrapping gibt es Einschränkungen. In diesem Fall muss möglicherweise ein HOC verwendet werden. Dann wäre die akzeptierte Antwort wertlos.
– Avius
26. Okt. 2021 um 13:20 Uhr
Im letzten Snippet sollte es lauten: login.doLogin(….
– Royi Namir
22. April 2022 um 20:01 Uhr
Auf jeden Fall können Sie eine funktionale zustandslose Komponente erstellen, die beispielsweise eine Komponente als Eingabe akzeptiert und eine andere Komponente als Ausgabe zurückgibt.
Sie können eine PrivateRoute-Komponente erstellen, die eine Komponente als Requisitenwert akzeptiert und eine andere Komponente zurückgibt, je nachdem, ob der Benutzer authentifiziert ist oder nicht.
Wenn der Benutzer nicht authentifiziert ist (lesen Sie ihn aus dem Kontextspeicher), leiten Sie den Benutzer mit zur Anmeldeseite weiter <Redirect to='/login'/>Andernfalls geben Sie die als Requisite übergebene Komponente zurück und senden andere Requisiten an diese Komponente <Component {...props} />
Komponenten höherer Ordnung müssen keine Klassenkomponenten sein. Ihr Zweck besteht darin, eine Komponente als Eingabe zu verwenden und gemäß einer bestimmten Logik eine Komponente als Ausgabe zurückzugeben.
Es sieht weniger aus wie ein HOC und eher wie eine Wrapper-Komponente. Ein HOC gibt den FC zurück, nicht ReactElement.
– Siraj Alam
21. Juni 2020 um 11:12 Uhr
Was ist, wenn ich hier eine Admin-Route haben möchte? wie kann ich es tun?
– Vinayak Shahdeo
10. Juli 2020 um 6:26
Unterstützt Ihre App also mehrere Autorisierungen, z. B. Benutzer und Administrator? Wenn ja, können Sie eine Komponente namens erstellen und prüfen, ob die Person Administrator ist (anstelle von isAuthenticated wie hier), sodass nur Personen mit der Eigenschaft „Administrator“ (überprüfen Sie anhand der Antwort der Authentifizierung) auf die Komponente zugreifen können
– onuriltan
10. Juli 2020 um 6:37 Uhr
Bitte sehen Sie sich die Antwort unten an und ändern Sie Ihre Antwort oder entfernen Sie sie. Ich weiß es zu schätzen, dass Sie versuchen zu helfen, aber die Antwort ist irreführend. Die private Route gibt keine Komponente zurück, obwohl das seltsam klingt. Eine Komponente ist in diesem Zusammenhang eine Funktion von Requisiten und nicht das, was einige JSX-Ergebnisse ergeben.
– Joel M
31. März 2021 um 0:04
Ihr habt Recht, aber ich kann meine Antwort nicht löschen, da sie akzeptiert wird
– onuriltan
15. Juli 2021 um 9:03 Uhr
Das Folgende ist ein stark vereinfachtes Beispiel für die Verwendung von HOC mit Funktionskomponenten.
Die zu „verpackende“ Funktionskomponente:
import React from 'react'
import withClasses from '../withClasses'
const ToBeWrappedByHOC = () => {
return (
<div>
<p>I'm wrapped by a higher order component</p>
</div>
)
}
export default withClasses(ToBeWrappedByHOC, "myClassName");
Die Komponente kann auf diese Weise in einer anderen Komponente verwendet werden.
<ToBeWrappedByHOC/>
Ich komme vielleicht zu spät zur Party, aber hier ist mein Kommentar zum HOC
Das Erstellen von HOC im Sinne einer echten Reaktionsfunktionskomponente ist nahezu unmöglich, da empfohlen wird, Hook nicht innerhalb einer verschachtelten Funktion aufzurufen.
Rufen Sie Hooks nicht innerhalb von Schleifen, Bedingungen oder verschachtelten Funktionen auf. Verwenden Sie stattdessen immer Hooks auf der obersten Ebene Ihrer React-Funktion, bevor Sie vorzeitig zurückkehren. Indem Sie diese Regel befolgen, stellen Sie sicher, dass Hooks bei jedem Rendern einer Komponente in derselben Reihenfolge aufgerufen werden. Dadurch kann React den Status von Hooks zwischen mehreren useState- und useEffect-Aufrufen korrekt beibehalten. (Wenn Sie neugierig sind, erklären wir Ihnen dies im Folgenden ausführlich.)
Obwohl der Code in codesandbox funktioniert, aber aufgrund der oben genannten Regel nicht auf Ihrem lokalen Computer ausgeführt werden kann, sollten Sie die folgende Fehlermeldung erhalten, wenn Sie versuchen, diesen Code auszuführen
React Hook "useState" cannot be called inside a callback