问题描述
我目前正在关注youtube上的教程,该教程使用来自webDevSimplified的react和socket.io构建whatsapp克隆:https://www.youtube.com/watch?v=tBr-PybP_9c
,这里是主要的回购协议:'https://github.com/WebDevSimplified/Whatsapp-Clone/tree/master/client
由于某种原因,我的自定义useConversation
钩返回了未定义的状态,而我的useContacts
钩却正常工作了。
这里是设置:
App.js:
import Dashboard from "./Dashboard";
import { ContactsProvider } from "../contexts/ContactsProvider";
import { Conversationsprovider } from "../contexts/Conversationsprovider";
import Test from "../components/test";///test
console.log(Test)//test purpose
function App() {
const [id,setId] = useLocalStorage("id");
const dashboard = (
<ContactsProvider>
<Conversationsprovider id={id}>
<Dashboard id={id} />
</Conversationsprovider>
</ContactsProvider>
);
return id ? dashboard : <Login onIdSubmit={setId} />;
}
export default App;
ContactsProvider.js
import React,{ useContext } from "react";
import useLocalStorage from "../hooks/useLocalStorage";
const ContactsContext = React.createContext();
export function useContacts() {
return useContext(ContactsContext);
}
export function ContactsProvider({ children }) {
const [contacts,setContacts] = useLocalStorage("contacts",[]);//initalValue an empty array
function createContact(id,name) {
setContacts((prevContacts) => {
return [...prevContacts,{ id,name }];
});
}
return (
<ContactsContext.Provider value={{ contacts,createContact }}>
{children}
</ContactsContext.Provider>
);
}
Contacts.js-我的useContacts
在这里工作
import React from "react";
import { ListGroup } from "react-bootstrap";
import { useContacts } from "../contexts/ContactsProvider";
export default function Contacts() {
const { contacts } = useContacts();
console.log(`contacts: ${contacts}`); //returns object,object as expected
return (
<ListGroup variant="flush">
{contacts.map((contact) => (//visibly working in UI when commenting out the ListGroup in conversations.js
<ListGroup.Item key={contact.id}>{contact.name}</ListGroup.Item>
))}
</ListGroup>
);
}
这是有问题的部分:
Conversationsprovider.js
import React,{ useContext } from "react";
import useLocalStorage from "../hooks/useLocalStorage";
import { useContacts } from "./ContactsProvider";
const ConversationsContext = React.createContext();
export function useConversations() {
return useContext(ConversationsContext);
}
export function Conversationsprovider({ children }) {
const [conversations,setConversations] = useLocalStorage(
"conversations",[]);//as well empty array
const { contacts } = useContacts();
function createConversation(recipients) {
setConversations((prevConversations) => {
return [...prevConversations,{ recipients,messages: [] }];
});
}
const formattedConversations = conversations.map((conversation) => {
const recipients = conversation.recipients.map((recipient) => {
const contact = contacts.find((contact) => {
return contact.id === recipient;
});
const name = (contact && contact.name) || recipient;
return { id: recipient,name };
});
return { ...conversation,recipients };
});
const value = {
conversations: formattedConversations,createConversation,};
return (
<ConversationsContext.Provider value={{ value }}>
{children}
</ConversationsContext.Provider>
);
}
以及导致错误的组件:
Conversations.js:
import React from "react";
import { ListGroup } from "react-bootstrap";
import { useConversations } from "../contexts/Conversationsprovider";
export default function Conversations() {
const { conversations } = useConversations();
console.log( `conversations: ${conversations}`)//returns undefined
return (
<ListGroup variant="flush">
{conversations.map((conversation,index) => (//can't map because conversations is undefined
<ListGroup.Item key={index}>
{conversation.recipients
.map(r => r.name)
.join(",")}
</ListGroup.Item>
))}
</ListGroup>
);
}
为清楚起见,这里是localStorage设置:
import { useEffect,useState } from 'react'
const PREFIX = 'whatsapp-clone-'
export default function useLocalStorage(key,initialValue) {
const prefixedKey = PREFIX + key;
const [value,setValue] = useState(() => {
const jsonValue = localStorage.getItem(prefixedKey);
if (jsonValue != null) return JSON.parse(jsonValue);
if (typeof initialValue === "function") {
return initialValue();
} else {
return initialValue;
}
});
useEffect(() => {
localStorage.setItem(prefixedKey,JSON.stringify(value));
},[prefixedKey,value]);
return [value,setValue];
}
我已经尝试解决这个问题了好几个小时了,而且想法不多了。我设置了一个test.js并将钩子导入到Test.js函数中。两者都分别返回其对象。
我已经使用npx create-react-app创建了应用程序,并通过yarn运行了它。
解决方法
问题出在您的ConversationsProvider.js
内:
const value = {
conversations: formattedConversations,createConversation,};
return (
<ConversationsContext.Provider value={{ value }}>
{children}
</ConversationsContext.Provider>
);
以下几行都相同:
<ConversationsContext.Provider value={{ value }}>
<ConversationsContext.Provider value={{ value: value }}>
<ConversationsContext.Provider value={{ value: { conversations: formattedConversations,createConversation: createConversation } }}>
执行时:
const { conversations } = useConversations();
conversations
将设置为undefined
,因为返回的对象仅具有属性value
。
要解决此问题,请通过更改以下行来删除嵌套:
<ConversationsContext.Provider value={{ value }}>
// to
<ConversationsContext.Provider value={value}>
PS。这里是提高您的调试技能的提示。您已经做到了:
const { conversations } = useConversations();
console.log(conversations);
哪个登录了undefined
。下一步将是不立即破坏对象,而是记录整个上下文值。
const contextValue = useConversations();
console.log(contextValue);
这将表明useConversations
返回的对象不是您期望的对象。