Fix components rerendering unnecessarily

Before, some providers (WebRtcProvider, CallProvider...) were rendered conditionally.
This was causing all their children to re-render when the provider rendered.

Instead of using conditional rendering, these providers now use `ConditionalContextProvider`.
It always renders the provider, but sets its value to `initialValue` if the dependencies are not all defined.
If all dependencies are defined, the value is the result of the `useProviderValue` hook.

Changes:
- New file: `ConditionalContextProvider`
- New file: `HookComponent` - Component that calls a hook when mounted and calls a `callback` function with the hook result as argument
- For `WebRtcProvider` and `CallProvider`, use `createOptionalContext` to create the context and `ConditionalContextProvider` to provide their value only when the conditions are met
- In `WebRtcProvider`, set the webRtcConnection to undefined when not in a call
- For all providers, wrap their `value` prop in `useMemo` to avoid unnecessary rerenders

Change-Id: Ide947e216d54599aabc71cf4bd026bd20d6e0daf
diff --git a/client/src/contexts/MessengerProvider.tsx b/client/src/contexts/MessengerProvider.tsx
index 51a19fb..c02a1b3 100644
--- a/client/src/contexts/MessengerProvider.tsx
+++ b/client/src/contexts/MessengerProvider.tsx
@@ -16,7 +16,7 @@
  * <https://www.gnu.org/licenses/>.
  */
 import { ConversationMessage, IConversation, LookupResult, WebSocketMessageType } from 'jami-web-common';
-import { createContext, ReactNode, useContext, useEffect, useState } from 'react';
+import { createContext, ReactNode, useContext, useEffect, useMemo, useState } from 'react';
 
 import { Contact } from '../models/contact';
 import { Conversation } from '../models/conversation';
@@ -105,17 +105,16 @@
     // return () => controller.abort() // crash on React18
   }, [accountId, searchQuery, axiosInstance]);
 
-  return (
-    <MessengerContext.Provider
-      value={{
-        conversations,
-        setSearchQuery,
-        searchResult,
-        newContactId,
-        setNewContactId,
-      }}
-    >
-      {children}
-    </MessengerContext.Provider>
+  const value = useMemo(
+    () => ({
+      conversations,
+      setSearchQuery,
+      searchResult,
+      newContactId,
+      setNewContactId,
+    }),
+    [conversations, setSearchQuery, searchResult, newContactId, setNewContactId]
   );
+
+  return <MessengerContext.Provider value={value}>{children}</MessengerContext.Provider>;
 };