So we have a an issue here when running NPM start, this is what I have received warnings when compiling, can't for the life of me figure this one out, this is my first ever question after years of using StackOverflow. I have now included my app.js and index.js, I'm sure i am doing something else wrong too as when I include //eslint-disable-next-line to all pages mentioned the localhost shows a white screen.
React Hook useEffect contains a call to 'setNewDevice'. Without a list of dependencies, this can lead to an infinite chain of updates. To fix this, pass [finishConfirmation] as a second argument to the useEffect Hook.
const Confirmed = props => {
const [newDevice, setNewDevice] = useState(false);
const [complete, setComplete] = useState(false);
const db = firebase.firestore();
useEffect(() => {
let email = window.localStorage.getItem("confirmationEmail");
if (!email) {
setNewDevice(true);
} else {
finishConfirmation(email);
}
});
React Hook useEffect has missing dependencies: 'moreInfoComplete', 'requestNotifications', and 'userState.userData.firstName'. Either include them or remove the dependency array.
const Dashboard = () => {
const [firstName, setFirstName] = useState(null);
const [lastName, setLastName] = useState(null);
const [moreInfoComplete, setMoreInfoComplete] = useState(false);
const { userState, userDispatch } = useContext(UserContext);
const { sendMessage } = useContext(ToastContext);
const db = firebase.firestore();
useEffect(() => {
if (
(moreInfoComplete || userState.userData.firstName) &&
"Notification" in window &&
Notification.permission === "default"
) {
requestNotifications();
}
}, []);
React Hook useEffect has missing dependencies: 'db', 'userDispatch', and 'userState.userData.pushTokenWeb'. Either include them or remove the dependency array.
const MainRouter = () => {
const [initializationComplete, setInitComplete] = useState(false);
const { userState, userDispatch } = useContext(UserContext);
const userId = userState.userId;
const db = firebase.firestore();
useEffect(() => {
sendPushNotification({
token: userState.userData.pushTokenWeb,
title: "Boop",
body: "shoop"
});
App.js
import React from "react";
import { ToastProvider } from "./contexts/toastContext";
import { UserProvider } from "./contexts/userContext";
import MainRouter from "./MainRouter";
const App = () => {
return (
<ToastProvider>
<UserProvider>
<MainRouter />
</UserProvider>
</ToastProvider>
);
};
export default App;
Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();
Related
I have a nextjs project and it has a react-rte component
the react-rte component is displayed correctly but when I go to some other component and click back in the browsers back button I get the following error:
Unhandled Runtime Error TypeError: r.getEditorState is not a function
When I comment out the react-rte componnet the error no longer occurs
react-rte component
import React, { useState, useEffect } from "react";
import dynamic from "next/dynamic";
import PropTypes from "prop-types";
//import the component
const RichTextEditor = dynamic(() => import("react-rte"), { ssr: false });
const MyStatefulEditor = ({ onChange }) => {
const [value, setValue] = useState([]);
console.log(value.toString("html"));
useEffect(() => {
const importModule = async () => {
//import module on the client-side to get `createEmptyValue` instead of a component
const module = await import("react-rte");
console.log(module);
setValue(module.createEmptyValue());
};
importModule();
}, []);
const handleOnChange = (value) => {
setValue(value);
if (onChange) {
onChange(value.toString("html"));
}
};
return <RichTextEditor value={value} onChange={handleOnChange} />;
};
MyStatefulEditor.propTypes = {
onChange: PropTypes.func,
};
export default MyStatefulEditor;
You can add a condition to check value before rendering RichTextEditor
import React, { useState, useEffect } from "react";
import dynamic from "next/dynamic";
import PropTypes from "prop-types";
import { useRouter } from "next/router";
//import the component
const RichTextEditor = dynamic(() => import("react-rte"), { ssr: false });
const MyStatefulEditor = ({ onChange }) => {
const [value, setValue] = useState();
const router = useRouter();
useEffect(() => {
const importModule = async () => {
//import module on the client-side to get `createEmptyValue` instead of a component
const module = await import("react-rte");
setValue(module.createEmptyValue());
};
importModule();
}, [router.pathname]);
const handleOnChange = (value) => {
setValue(value);
if (onChange) {
onChange(value.toString("html"));
}
};
//if `value` from react-rte is not generated yet, you should not render `RichTextEditor`
if (!value) {
return null;
}
return <RichTextEditor value={value} onChange={handleOnChange} />;
};
MyStatefulEditor.propTypes = {
onChange: PropTypes.func
};
export default MyStatefulEditor;
You can verify the implementation with the live example and the sandbox
Try this
import React, { useState, useEffect } from "react";
import dynamic from "next/dynamic";
import PropTypes from "prop-types";
const RichTextEditor = dynamic(() => import("react-rte"), { ssr: false });
const MyStatefulEditor = ({ onChange }) => {
const [value, setValue] = useState([]);
useEffect(() => {
// set the state value using the package available method
setValue(RichTextEditor.createEmptyValue())
}, []);
const handleOnChange = (value) => {
setValue(value);
if (onChange) {
onChange(value.toString("html"));
}
};
return <RichTextEditor value={value} onChange={handleOnChange} />;
};
MyStatefulEditor.propTypes = {
onChange: PropTypes.func,
};
export default MyStatefulEditor;
Like I mention in my previous comment, I notice you are importing the react-rte package twice.
In the useEffect hook you do an import to initialise the value state, by looking at the example code found here
You can achieve that using RichTextEditor.createEmptyValue() which comes from the already imported package.
You will noticed that I change the import, is not dynamic, try that and if is it works if so then try doing the dynamic import if that is what you need.
How do I print out the values I see in my console? I need to display them in the app I am running in React Native using Expo. Do I need to map through the object array and print out values, or run the MyProfile a different way because it is asynced?
Thanks!
import { useNavigation } from "#react-navigation/core";
import React, { useEffect, useState } from "react";
import firebase from "firebase/app";
import "firebase/firestore";
import { auth } from "../firebase";
import {
Text,
View,
StyleSheet,
Image,
SafeAreaView,
ScrollView,
TouchableOpacity,
} from "react-native";
import { Animate } from "react-native-entrance-animation";
import Copyright from "./Copyright";
const ProfileScreen = () => {
const navigation = useNavigation();
const MyProfile = () => {
const [posts, setPosts] = useState(null);
let myPosts = "Profile loading...";
const collectIdsAndDocs = (doc) => {
return { id: doc.id, ...doc.data() };
};
useEffect(() => {
const getPost = async () => {
const snapshot = await firebase
.firestore()
.collection("profiles")
.where("email", "==", auth.currentUser.email)
.get();
myPosts = snapshot.docs.map(collectIdsAndDocs);
console.log(myPosts);
setPosts({ myPosts });
};
getPost();
}, []);
return (
<View>
<Text>{/*how do I print out values here!? I see them in console*/}</Text>
</View>
);
};
Since you already calls the setPosts useState hook, you can access posts in your rendering code:
return (
<View>
{posts.map((post) => (
<Text>{post.id}</Text>
))}
</View>
);
To solve the null problem, pass in an empty array as the initial value when you define the state:
const [posts, setPosts] = useState([]);
In my Main.js I create a first global state with a username and a list of users I'm following.
Then, both the Wall component and FollowingSidebar render the list of follows and their messages (plus the messages of the main user).
So far so good. But in a nested component inside FollowingSidebar called FollowingUser I have an onClick to remove a user. My understanding is that, because I change the state, useEffect would take care of the Wall component to re-render it, but nothing happens... I've checked several examples online but nothing has helped my use case so far.
Needless to say I'm not overly experienced with React and Hooks are a bit complex.
The code here:
Main.js:
import React, { useEffect, useState } from "react";
import ReactDom from "react-dom";
import db from "./firebase.js";
// Components
import Header from "./components/Header";
import FollowingSidebar from "./components/FollowingSidebar";
import SearchUsers from "./components/SearchUsers";
import NewMessageTextarea from "./components/NewMessageTextarea";
import Wall from "./components/Wall";
// Context
import StateContext from "./StateContext";
function Main() {
const [mainUser] = useState("uid_MainUser");
const [follows, setFollows] = useState([]);
const setInitialFollows = async () => {
let tempFollows = [mainUser];
const user = await db.collection("users").doc(mainUser).get();
user.data().following.forEach(follow => {
tempFollows.push(follow);
});
setFollows(tempFollows);
};
useEffect(() => {
setInitialFollows();
}, []);
const globalValues = {
mainUserId: mainUser,
followingUsers: follows
};
return (
<StateContext.Provider value={globalValues}>
<Header />
<FollowingSidebar />
<SearchUsers />
<NewMessageTextarea />
<Wall />
</StateContext.Provider>
);
}
ReactDom.render(<Main />, document.getElementById("app"));
if (module.hot) {
module.hot.accept();
}
FollowingSidebar component:
import React, { useState, useEffect, useContext } from "react";
import db from "../firebase.js";
import StateContext from "../StateContext";
import FollowingUser from "./FollowingUser";
export default function FollowingSidebar() {
const { followingUsers } = useContext(StateContext);
const [users, setUsers] = useState(followingUsers);
useEffect(() => {
const readyToRender = Object.values(followingUsers).length > 0;
if (readyToRender) {
db.collection("users")
.where("uid", "in", followingUsers)
.get()
.then(users => {
setUsers(users.docs.map(user => user.data()));
});
}
}, [followingUsers]);
return (
<section id="following">
<div className="window">
<h1 className="window__title">People you follow</h1>
<div className="window__content">
{users.map((user, index) => (
<FollowingUser avatar={user.avatar} username={user.username} uid={user.uid} key={index} />
))}
</div>
</div>
</section>
);
}
FollowingUser component:
import React, { useState, useContext } from "react";
import db from "../firebase.js";
import firebase from "firebase";
import StateContext from "../StateContext";
export default function FollowingUser({ avatar, username, uid }) {
const { mainUserId, followingUsers } = useContext(StateContext);
const [follows, setFollows] = useState(followingUsers);
const removeFollow = e => {
const userElement = e.parentElement;
const userToUnfollow = userElement.getAttribute("data-uid");
db.collection("users")
.doc(mainUserId)
.update({
following: firebase.firestore.FieldValue.arrayRemove(userToUnfollow)
})
.then(() => {
const newFollows = follows.filter(follow => follow !== userToUnfollow);
setFollows(newFollows);
});
userElement.remove();
};
return (
<article data-uid={uid} className="following-user">
<figure className="following-user__avatar">
<img src={avatar} alt="Profile picture" />
</figure>
<h2 className="following-user__username">{username}</h2>
<button>View messages</button>
{uid == mainUserId ? "" : <button onClick={e => removeFollow(e.target)}>Unfollow</button>}
</article>
);
}
Wall component:
import React, { useState, useEffect, useContext } from "react";
import db from "../firebase.js";
import Post from "./Post";
import StateContext from "../StateContext";
export default function Wall() {
const { followingUsers } = useContext(StateContext);
const [posts, setPosts] = useState([]);
useEffect(() => {
console.log(followingUsers);
const readyToRender = Object.values(followingUsers).length > 0;
if (readyToRender) {
db.collection("posts")
.where("user_id", "in", followingUsers)
.orderBy("timestamp", "desc")
.get()
.then(posts => setPosts(posts.docs.map(post => post.data())));
}
}, [followingUsers]);
return (
<section id="wall">
<div className="window">
<h1 className="window__title">Latest messages</h1>
<div className="window__content">
{posts.map((post, index) => (
<Post avatar={post.user_avatar} username={post.username} uid={post.user_id} body={post.body} timestamp={post.timestamp.toDate().toDateString()} key={index} />
))}
</div>
</div>
</section>
);
}
StateContext.js:
import { createContext } from "react";
const StateContext = createContext();
export default StateContext;
The main issue is the setting of state variables in the Main.js file (This data should actually be part of the Context to handle state globally).
Below code would not update our state globally.
const globalValues = {
mainUserId: mainUser,
followingUsers: follows
};
We have to write state in a way that it get's modified on the Global Context level.
So within your Main.js set state like below:
const [globalValues, setGlobalValues] = useState({
mainUserId: "uid_MainUser",
followingUsers: []
});
Also add all your event handlers in the Context Level in Main.js only to avoid prop-drilling and for better working.
CODESAND BOX DEMO: https://codesandbox.io/s/context-api-and-rendereing-issue-uducc
Code Snippet Demo:
import React, { useEffect, useState } from "react";
import FollowingSidebar from "./FollowingSidebar";
import StateContext from "./StateContext";
const url = "https://jsonplaceholder.typicode.com/users";
function App() {
const [globalValues, setGlobalValues] = useState({
mainUserId: "uid_MainUser",
followingUsers: []
});
const getUsers = async (url) => {
const response = await fetch(url);
const data = await response.json();
setGlobalValues({
...globalValues,
followingUsers: data
});
};
// Acts similar to componentDidMount now :) Called only initially
useEffect(() => {
getUsers();
}, []);
const handleClick = (id) => {
console.log(id);
const updatedFollowingUsers = globalValues.followingUsers.filter(
(user) => user.id !== id
);
setGlobalValues({
...globalValues,
followingUsers: updatedFollowingUsers
});
};
return (
<StateContext.Provider value={{ globalValues, handleClick }}>
<FollowingSidebar />
</StateContext.Provider>
);
}
export default App;
I made frontend app in React.js.
I wrote codes in App.js of frontend like
import React, { Fragment, useState, useEffect, Component, View } from 'react';
import axios from 'axios';
import Routes from '../src/components/Routes';
import TopNavigation from './components/topNavigation';
import SideNavigation from './components/sideNavigation';
import Footer from './components/Footer';
import './index.css';
import Router from './Router';
const App = () => {
const [user, setLogin] = useState(null)
const [report, setReport] = useState(null)
useEffect(()=>{
login().then(user => setLogin(user))
}, [])
useEffect(()=>{
getReport().then(report => setReport(report))
}, [])
return <div>
{user != null? <p>name: {user.name}</p>:<button>Login</button>}
</div>
}
export default App;
I wrote in this code login().then(user => setLogin(user)) whether user already logined or not.
Login system was made in Django,so I want to use it.I think React has login method but I really cannot understand what is wrong.How should I fix this?
I can see nowhere login is defined in your code. If you've written login on other files, you should import it.
Actually, I cannot understand what you mean by this - "I think React has login method but ...". React doesn't support any predefined login method.
You should define login method yourself something like this.
const API_URL = 'some url';
const login = async (body) => {
const response = await axios.post(`${API_URL}/login`, body);
return response.json();
};
const App = () => {
const [user, setLogin] = useState(null);
const [report, setReport] = useState(null);
useEffect(() => {
login({
email: 'email#some.com',
password: 'some password'
}).then((user) => setLogin(user));
}, []);
useEffect(() => {
getReport().then((report) => setReport(report));
}, []);
};
I am trying to history.push but its always undefined.
import React, { useEffect, useState } from "react";
import * as Firebase from "firebase/app";
import "firebase/auth";
import DBAPI from "./database/database-api"
import DBName from "./database/database-name"
import { useHistory } from "react-router-dom";
export const UserContext = React.createContext();
export const UserProvider = ({ children }) => {
const [currentUser, setCurrentUser] = useState(null);
const [isAdmin, setIsAdmin] = useState(null);
const [isVendor, setIsVendor] = useState(null);
const [pending, setPending] = useState(true);
let history = useHistory();
useEffect(() => {
Firebase.auth().onAuthStateChanged(async (user) => {
if (user != null) {
setCurrentUser(user)
let response = await Promise.all([
DBAPI.checkUserExist(DBName.admin, user.uid),
DBAPI.checkUserExist(DBName.vendor, user.uid)
]);
console.log(response[0].data)
console.log(response[1].data)
if (response[0].data) setIsAdmin(true) // admin
if (response[1].data) setIsVendor(true) // vendor
history.push(`${process.env.PUBLIC_URL}/products`)
} else {
setIsVendor(false)
setIsAdmin(false)
}
setPending(false)
});
}, []);
if(pending){
return <>Loading...</>
}
return (
<UserContext.Provider
value={{
currentUser,
isAdmin,
isVendor
}}
>
{children}
</UserContext.Provider>
);
};
The code looks ok. Just make sure your component is wrapped in a <Router> context.