I don't understand why my useEffect is not being called? I'm following a Youtube tutorial right now and all my code looks exactly the same as in the video. I was reading this: useEffect not being called and not updating state when api is fetched but I couldn't relate it to my problem so I was wondering if anyone could help me on this.
Thanks so much.
import { useSession } from "next-auth/react";
import { ChevronDownIcon } from "#heroicons/react/outline";
import { useEffect, useState } from "react";
import { shuffle } from "lodash";
const colors = [
"from-indigo-500",
"from-blue-500",
"from-green-500",
"from-red-500",
"from-yellow-500",
"from-pink-500",
"from-purple-500",
];
function Center() {
const { data: session } = useSession();
const [color, setColor] = useState(null);
useEffect(() => {
console.log("useEffect called");
setColor(shuffle(colors).pop());
}, []);
return (
<div className="flex-grow">
<header className="absolute top-5 right-8">
<div className="flex items-center bg-red-300 space-x-3 opacity-90 hover:opacity-80 cursor-pointer rounded-full p-1 pr-2">
<img
className="rounded-full w-10 h-10"
src={session?.user.image}
alt=""
/>
<h2>{session?.user.name}</h2>
<ChevronDownIcon className="h-5 w-5" />
</div>
</header>
<section
className={
"flex items-end space-x-7 bg-gradient-to-b to-black ${colors} h-80 text-white padding-8"
}
>
<h1>hello</h1>
</section>
</div>
);
}
export default Center;
MRE:
import { useEffect, useState } from "react";
const colors = [
"from-indigo-500",
"from-blue-500",
"from-green-500",
"from-red-500",
"from-yellow-500",
"from-pink-500",
"from-purple-500",
];
function Center() {
const [color, setColor] = useState(null);
useEffect(() => {
console.log("useEffect called");
}, []);
return (
<div className="flex-grow">
<section
className={
"flex items-end space-x-7 bg-gradient-to-b to-black ${colors} h-80 text-white padding-8"
}
>
</section>
</div>
);
}
export default Center;
FINALLY SOLVED!!!
${colors} should've been ${color} and everything in className={} needs to be surrounded by `` not "". I originally thought useEffect() wasn't even been called because I was looking at VSCode terminal instead of chrome console.
Maybe sounds obvious, but are you sure you didn't filter out your console log from chrome developer tools? The default shows info, warnings and errors but I often filter one and next time I open the console have to reset it.
Related
I am creating dev.to clone for react js practice when
trying to render markdown in react-markdown it doesn't render properly,
here it is:
Post.js
import React, { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import SyntexHighlight from '../../components/SyntexHighlight';
const Post = ({ post }: any) => {
return (
<main className="h-full bg-white rounded-md border">
<header>
.........
</header>
<div
className=" leading-8 marker:text-black max-w-2xl mx-auto py-6 prose
prose-lg prose-p:block prose-li:py-[0.5] prose-li:my-0 prose-a:text-blue-600
hover:prose-a:text-blue-500 prose-code:text-sm prose-code:bg-gray-200
prose-code:p-1 prose-code:rounded prose-img:mx-auto "
>
<ReactMarkdown components={SyntexHighlight}>{post.body}</ReactMarkdown>
</div>
<section className="border-t-2 px-8 py-4">
........
</section>
</main>
);
};
export default Post;
SyntexHighlight.js
import React from 'react';
import { Prism } from 'react-syntax-highlighter';
import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
const SyntexHighlight = {
code({ node, inline, className, ...props }: any) {
const match = /language-(\w+)/.exec(className || '');
return !inline && match ? (
<Prism style={oneDark} language={match[1]} PreTag="div" className="codeStyle" {...props} />
) : (
<code className={className} {...props} />
);
},
};
export default SyntexHighlight;
It doesn't render properly
markdown render problem
markdown render problem
markdown render problem
I tried "json2md" package after getting JSON string form node server still not working
when i try "json2md" data to separate variable
data variable
<div
className=" leading-8 marker:text-black max-w-2xl mx-auto py-6 prose
prose-lg prose-p:block prose-li:py-[0.5] prose-li:my-0 prose-a:text-blue-600
hover:prose-a:text-blue-500 prose-code:text-sm prose-code:bg-gray-200
prose-code:p-1 prose-code:rounded prose-img:mx-auto "
>
<ReactMarkdown components={SyntexHighlight}>{MarkdownFile}</ReactMarkdown>
</div>
Now its working properly
it's working
it's working
it's working
i don't know what is the problem ???
import React,{ useEffect, useState} from 'react';
import { useLocation } from 'react-router-dom';
import ReactPlayer from 'react-player';
import { useResultContext } from '../contexts/ResultContextProvider';
export const Results = () => {
const {getResults, results, isLoading, searchTerm} = useResultContext();
const location = useLocation();
const [num, setNum] = useState(10);
const changeNum=()=>{
setNum(num+10);
console.log(num)
Results();
}
useEffect(()=>{
if(searchTerm){
if (location.pathname ==='/videos') {
getResults(`/search/q=${searchTerm} videos&num=${num}`)
}else{
getResults(`${location.pathname}/q=${searchTerm}&num=${num}`)
}
}
},[location.pathname, searchTerm, num, getResults]);
switch (location.pathname) {
case '/search':
return (<><div className='flex flex-wrap justify-between space-y-6 sm:px-56 overflow-hidden pb-4 '>
{
results?.results?.map(({link, title, description}, index)=>(
<div key={index} className='md:w-3/5 w-full'>
<a href={link} target="_blank" rel="noreferrer">
<p className='text-sm text-green-700'>
{link.length>50? link.substring(0,50): link}
</p>
<p className='text-lg hover:underline dark:text-blue-300 text-blue-700'>
{title}
</p>
</a>
{description.length>15?
<p>
{description}
</p>:''}
</div>
))
}
</div>
<div onClick={changeNum} className='absolute bg-gray-200 border border-gray-400 py-3 px-10 rounded-full -mt-5 left-96 cursor-pointer active:bg-gray-300 dark:bg-gray-700 '>
More Results
</div>
</>);
default: return 'ERROR';
}
};
I've started learning react and it's been two days i have been unable to get around this.
I'm trying to make google search engine clone and in this project i'm getting results using google search api and displaying 10 results at first and want then to increase by 10 every time when i click on 'More Results' button which calls 'changeNum' function which uses 'setNum' to add 10 value to 'num' every time function is called by clicking on button.
EDIT: i shortened the code by removing some cases
const changeNum=()=>{
setNum(num+10);
console.log(num)
Results(); <--------
}
Calling your functional component like this is what is causing the error. This line is not needed as your component will update when you update the state.
Im trying to make a Modal and when someone clicks to open it I want to disable scrollbar.
My Modal is a component and I cant pass the prop "open" to the condition. When someone clicks to open the Modal the condition doesn't work and the scrollball stays.
My Dialog.js is where I have my array and my functions, I pass them as props to the others components, to each individual Modal.
Dialog.js
export default function Dialog() {
let [Dentisteria, setDentisteria] = useState(false);
let [Endodontia, setEndodontia] = useState(false);
let [Ortodontia, setOrtodontia] = useState(false);
const dataEspecialidades = [
{
setOpen: setDentisteria,
open: Dentisteria,
},
{
setOpen: setEndodontia,
open: Endodontia,
},
{
id: 3,
setOpen: setOrtodontia,
open: Ortodontia,
},
];
return (
<>
<div className="grid gap-8 mx-auto md:grid-cols-3">
{dataEspecialidades.map((item) => {
return (
<>
<Card setOpen={item.setOpen}>
<CardTitle>{item.title}</CardTitle>
<CardDescription>{item.text}</CardDescription>
</Card>
<Modal setOpen={item.setOpen} open={item.open}>
<ModalTitle>{item.title}</ModalTitle>
<ModalDescription>
{item}
</ModalDescription>
</Modal>
</>
);
})}
</div>
</>
);
}
My Card component is used to open the Modal and its working. I pass the prop
setOpen that I have in my Dialog.js.
Card.js
export function Card({ setOpen, children }) {
return (
<>
<div
onClick={() => setOpen(true)}
className="px-4 py-6 text-center rounded-lg cursor-pointer select-none bg-gradient-to-br from-white to-neutral-50 drop-shadow-lg"
>
{children}
</div>
</>
);
}
My Modal component is used to show and close the Modal and its working. I pass the prop setOpen and open that I have in my Dialog.js.
But the open prop is not working in the condition to hide the scrollbar when the Modal is open.
Modal.js
export function Modal({ open, setOpen, children }) {
if (typeof document !== "undefined") {
if (open) {
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "";
}
}
return (
<>
<div
className={`${open ? "" : "hidden"} fixed z-10 inset-0 overflow-y-auto`}
>
<div className="flex items-center justify-center min-h-screen p-4">
<div className="fixed inset-0 bg-black opacity-30"></div>
<div className="relative w-full max-w-2xl p-8 mx-auto bg-white rounded-lg">
{children}
</div>
</div>
</div>
</>
);
}
You are not tracking open with a state, you could use the useEffect hook for this
https://reactjs.org/docs/hooks-effect.html
const [modalIsOpen, setmodalIsOpen] = useState(open);
useEffect(() => {
// Update the body style when the modalIsOpenState changes
if (modalIsOpen) {
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "";
}
}, [modalIsOpen]); // adding this will run useEffect any time modalIsOpen changes see the "Tip: Optimizing Performance by Skipping Effects" part of the documentation for more details
I realise your question is for next.js. I'm used to using React myself, you can use my answer in your Next.js application by importing useEffect like this
import React, { useState, useEffect } from 'react'
I'm using a 3rd party API https://www.metaweather.com and in my package.json i've added
"proxy": "https://www.metaweather.com",
My app.js is as follows:
import { createContext, useState } from "react";
import LocationSearch from "./components/locationSearch";
import MainWeather from "./components/mainWeather";
import ExtraWeather from "./components/ExtraWeather";
export const DisplayContext = createContext({
display: false,
setDisplay: () => {},
});
function App() {
const [woeid, setWoeid] = useState(null);
const [display, setDisplay] = useState(false);
return (
<DisplayContext.Provider value={{ display, setDisplay }}>
<LocationSearch setWoeid={setWoeid} />
<MainWeather woeid={woeid} />
<ExtraWeather />
</DisplayContext.Provider>
);
}
export default App;
my LocationSearch.jsx:
import React, { useContext, useState } from "react";
import axios from "axios";
import { DisplayContext } from "../App";
const LocationSearch = ({ setWoeid }) => {
const [data, setData] = useState({
location: "",
});
const { setDisplay } = useContext(DisplayContext);
function submit(e) {
e.preventDefault();
axios
.get(
// "https://cors-anywhere.herokuapp.com/https://www.metaweather.com/api/location/search/?query=" +
"/api/location/search/?query=" +
data.location,
{
location: data.location,
}
)
.then((res) => {
console.log(res.data[0].woeid);
setWoeid(res.data[0].woeid);
setTimeout(() => setDisplay(true), 5000);
})
.catch((err) => {
console.log(err);
});
}
function handle(e) {
const newdata = { ...data };
newdata[e.target.id] = e.target.value;
setData(newdata);
console.log(newdata);
}
return (
<div className="flex w-96 mx-auto mt-5 p-3 rounded-xl bg-blue-300">
<form className="flex w-96 mx-auto p-3 rounded-xl bg-white">
<div>
<input
className="text-gray-700"
onChange={(e) => handle(e)}
id="location"
value={data.location}
placeholder="Search for location"
type="text"
/>
<button
className="bg-blue-900 text-gray-300 py-3 px-5 ml-12 rounded-xl"
type="submit"
onClick={(e) => submit(e)}
>
Search
</button>
</div>
</form>
</div>
);
};
export default LocationSearch;
my MainWeather.jsx:
import React, { useContext, useEffect, useState } from "react";
import axios from "axios";
import { DisplayContext } from "../App";
import Loader from "react-loader-spinner";
const MainWeather = ({ woeid }) => {
const [temp, setTemp] = useState([]);
const [icon, setIcon] = useState("");
const { display } = useContext(DisplayContext);
const [load, setLoad] = useState(false);
useEffect(() => {
axios
.get(
// "https://cors-anywhere.herokuapp.com/https://www.metaweather.com/api/location/" +
"/api/location/" +
woeid
)
.then((res) => {
setLoad(true);
console.log(res.data[0]);
setIcon(res.data.consolidated_weather[0].weather_state_abbr);
setTemp((prev) => {
return [
...prev,
res.data.consolidated_weather[0].the_temp,
res.data.consolidated_weather[0].min_temp,
res.data.consolidated_weather[0].max_temp,
res.data.consolidated_weather[0].weather_state_name,
];
});
})
.catch((err) => {
console.log(err);
});
}, [woeid]);
return (
<>
{display && (
<div className="w-96 flex flex-col mx-auto p-3 mt-2 rounded-xl bg-blue-300">
<img
src={"/static/img/weather/" + icon + ".svg"}
alt="Current weather icon"
className="w-40 mx-auto pb-4"
/>
<p className="mx-auto text-5xl pb-3">{Math.round(temp[0])}°C</p>
<p className="mx-auto pb-1">
{Math.round(temp[1])} / {Math.round(temp[2])}
</p>
<p className="mx-auto pb-2">{temp[3]}</p>
</div>
)}
{!display && (
<div>
{load && (
<div className="flex w-96 h-80 mx-auto mt-5 p-3 rounded-xl bg-blue-300">
<Loader
className="m-auto"
type="Puff"
color="#00BFFF"
height={100}
width={100}
timeout={5000}
/>
</div>
)}
{!load && (
<div className="flex w-96 h-80 mx-auto mt-5 p-3 rounded-xl bg-blue-300">
<h1 className="m-auto">Please enter a location</h1>
</div>
)}
</div>
)}
</>
);
};
export default MainWeather;
The ExtraWeather.jsx isn't relevant.
If I comment out the MainWeather and log the return from the LocationSearch it returns to object perfectly but as soon as I introduce the MainWeather back I get "CORS header ‘Access-Control-Allow-Origin’ missing" error. I've tried everything I can find from hosting the app on Netlify, changing what is the proxy to the local host address, moving things to different places, and I'm unsure if I did it correctly but I did try a reverse proxy.
Also using herokuapp and a browser extension does fix the problem but I want something more permanent.
Any help will be greatly appreciated.
The issue is that the response is being redirected to include a / suffix, ie
HTTP/2 301
location: https://www.metaweather.com/api/location/44418/
This causes your browser to re-attempt the request to that URL which bypasses your proxy.
Try including the / suffix, eg
axios.get(`/api/location/${woeid}/`)
Keep in mind that the proxy setting only works for local development. If you're deploying to Netlify, see https://docs.netlify.com/routing/redirects/rewrites-proxies/#proxy-to-another-service
Debugging Process
Something was directing your browser to try and access the API by its full URL so I suspected a redirect.
I just ran
curl -v "https://www.metaweather.com/api/location/44418" -o /dev/null
and looked at the response status and headers...
> GET /api/location/44418 HTTP/2
> Host: www.metaweather.com
< HTTP/2 301
< location: https://www.metaweather.com/api/location/44418/
Spotting the difference was the hard part 😄
You could probably have seen something similar in your browser dev-tools Network panel; first a request to /api/location/44418 with a 301 response and location header, then a request to https://www.metaweather.com/api/location/44418/ which failed CORS checks
I'm developing a blog on next.js with sanity.io, and I'm having trouble using the code-input plugin.
What I do have
I'm able to use the code component block on sanity, which looks something like this:
Everything good on the sanity side. My problem comes with using it on the next.js [slug].js file.
I have this error prompt out:
This issue with this is that I don't have a serializer.js file/component anywhere on my code, not even on the studio root folder. I've seen this applies for gatsby but I don't know how to apply it for Next.js
This is what I currently Have:
import groq from 'groq'
import imageUrlBuilder from '#sanity/image-url'
import BlockContent from '#sanity/block-content-to-react'
import client from '../../client'
import Layout from '../../components/layout'
import utilStyles from '../../styles/utils.module.css'
import styles from '../../components/layout.module.css'
function urlFor (source) {
return imageUrlBuilder(client).image(source)
}
const Post = (props) => {
const {
title = 'Missing title',
name = 'Missing name',
categories,
authorImage,
mainImage,
code,
body = []
} = props
console.log(props)
return (
<Layout>
<article>
<div className={styles.container}>
<figure>
<img src={urlFor(mainImage).url()} />
</figure>
<h1 className={utilStyles.headingXl}>{title}</h1>
{categories && (
<ul className="inline">
Category:
{categories.map(category =>
<li key={category}>
<span className="inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-indigo-100 bg-indigo-700 rounded">{category}</span>
</li>)}
</ul>
)}
<BlockContent
blocks={body}
imageOptions={{fit: 'max'}}
{...client.config()}
{...code}
/>
</div>
</article>
</Layout>
)
}
const query = groq ` *[_type == "post" && slug.current == $slug][0]{
title,
"name": author->name,
"categories": categories[]->title,
mainImage,
code,
"authorImage": author->image,
body,
}`
Post.getInitialProps = async function(context) {
const {slug = ""} = context.query
return await client.fetch(query, { slug })
}
export default Post
I really would appreciate some help here! Thanks <3
You can pass a serializer for the code block type to your BlockContent using the serializers prop.
const serializers = {
types: {
code: props => (
<pre data-language={props.node.language}>
<code>{props.node.code}</code>
</pre>
)
}
}
// ...
<BlockContent
blocks={body}
imageOptions={{fit: 'max'}}
{...client.config()}
{...code}
serializers={serializers}
/>