so I have this javascript code that I want to use in React react, it's working so far, so this is what I got, first of all
THIS IS MY JAVASCRIPT CODE the one that I want to turn into GATSBY react JSX
function onLoad() {
var showDiv;
if(localStorage.getItem ("showDiv") == null) {
showDiv = true;
}
else {
showDiv = localStorage.getItem ("showDiv")
}
if (showDiv) {
document.getElementById ('myDiv') .style.display = 'block';
}
else {
document.getElementById ('myDiv') .remove();
}
}
function onClose() {
document.getElementById ('myDiv') .remove();
localStorage.setItem("showDiv", false);
}
AND THIS IS WHAT I GOT SO FAR, its working but I don't know how to code the onClose function the one right above from the javascript code
SO THIS IS MY COMPONENT
import React, { useEffect } from 'react';
import '../index.css'
export default function Com() {
useEffect(() => {
var showDiv;
if (localStorage.getItem ("showDiv") == null) {
showDiv = true;
}
else {
showDiv = localStorage.getItem ("showDiv")
}
if (showDiv) {
document.querySelector ('.contenedor').style.display = 'block';
}
else {
document.querySelector ('.contenedor').remove();
}
() => {
document.querySelector ('.contenedor').remove(); /* THIS IS THE ANONYMOUS FUNCTION */
localStorage.setItem("showDiv", false);
}
}, []);
return (
<div className="contenedor" style={{display: "none"}}>
<img className="portada" src="https://res.cloudinary.com/lenguaestudiocreativo/image/upload/v1626228418/hportada_jgljqd.svg" alt=""/>
</div>
);
}
And so this is my main index:
import React from 'react';
import './index.css';
import Com from './componentes/Comdos';
export default function index() {
return (
<Com />
)
};
I tried to use this anonymous function but it doesn't work, of course, if I remove this anonymous function it works right, but I also need this last part of the code, the onClose function, if the anonymous function doesn't work then how do I code this?
and so this is the error that I'm getting with the anonymous function
ERROR in
C:\Users\USUARIO\Downloads\VSCODE\JSXejercicios\landingpage\src\pages\componentes\Comdos.js
22:10 error Expected an assignment or function call and instead saw
an expression no-unused-expressions
✖ 1 problem (1 error, 0 warnings)
you can use react useState and useEffect hooks, try this one :
import React, { useState, useEffect } from "react";
export default function App() {
const [show, setShow] = useState(true);
useEffect(() => {
if (localStorage.getItem("showDiv") == null)
localStorage.setItem("showDiv", show);
}, []);
function togglePic() {
setShow(!show ? true : false);
localStorage.setItem("showDiv", !show);
}
return (
<>
<button onClick={togglePic}>Click to toggle the picture</button>
<div className="contenedor" style={{ display: show ? "block" : "none" }}>
<img
className="portada"
src="https://static.wikia.nocookie.net/spongebob/images/3/3e/SpongeBob_Star_show.jpeg"
alt=""
/>
</div>
</>
);
}
Reference:
Here are some references you can explore more
ReactJs Documentation - Conditional Rendering
ReactJs Documentation - Handling Events
ReactJs Documentation - Hooks State
ReactJs Documentation - Hooks Effect
Code Example:
try live code using CodeSanbox
Code Sanbox -
Demo
Related
Can you use useState (and other react hooks?) with Server Side Rendering? Everytime I am trying to run the code below I get the error TypeError: Cannot read property 'useState' of null. However, when I comment out the getServerSideProps function at the very bottom I have no problem running the code as intended. So my questions is can useState be used with Server Side Rendering in nextjs? If the answer is yes, then where am I going wrong in the code below?
import React from "react";
import { useRouter } from "next/router";
import useSelectedGenreInfoExtractor from "../../hooks/useSelectedGenreInfoExtractor";
import { useState } from "react";
import { useEffect } from "react";
import Navbar from "../../components/Navbar";
import useFetchTrendingCatagory from "../../hooks/useFetchTrendingCatagory";
import useFetchTopRatedCatagory from "../../hooks/useFetchTopRatedCatagory";
import useFetchMovieGenreResults from "../../hooks/useFetchMovieGenreResults";
import Moviegenreresults from "../../components/Moviegenreresults";
export default function genre(props) {
const [myresultsfromhook, setMyresultsfromhook] = useState();
const [myreturnedmovies, setMyreturnedmovies] = useState();
const router = useRouter();
const { genre } = router.query;
if (genre == "Trending") {
let mymovies = useFetchTrendingCatagory();
console.log("This is a log of my props", props);
return (
<div>
{/* <Navbar /> */}
<div>{genre}</div>
<Moviegenreresults movies={mymovies} />
</div>
);
} else if (genre == "Top Rated") {
let mymovies = useFetchTopRatedCatagory();
return (
<div>
{/* <Navbar /> */}
<div>{genre}</div>
<Moviegenreresults movies={mymovies} />
</div>
);
} else {
let mymovies = useFetchMovieGenreResults(genre);
return (
<div>
{/* <Navbar /> */}
<div>{genre}</div>
<Moviegenreresults movies={mymovies} />
</div>
);
}
}
export async function getServerSideProps(context) {
if (context.params.genre == "Trending") {
let mymovies = useFetchTrendingCatagory();
return {
props: {
results: mymovies.results,
},
};
} else if (context.params.genr == "Top Rated") {
let mymovies = useFetchTopRatedCatagory();
return {
props: {
results: mymovies.results,
},
};
} else {
let mymovies = useFetchMovieGenreResults(genre);
return {
props: {
results: mymovies.results,
},
};
}
}
I think fundamentally the problem is the way you are using getServerSideProps.
Even thought the answer is you can not use useState inside getServerSideProps because this function run in the server, it is important to understand what getServerSideProps does and when, I think you can find very clear explanation about that in next docs.
https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props
Inside getServerSideProps use axios or the fetch api to get your data and pass it to the props.
I am not 100% sure but I thinnk inn your case you can also use Promise.all() to get the data from those three api calls.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
useState should be inside the component, it is a React hook. serverside functions are independent of React components.
I think the issue is the name of the component should be with capital letter:
// not genre
export default function Genre(props)
I have a navbar with position sticky and when I go up to top 0 I change the color, using useRef, I apply a class .ToolbarSticky when the getBoundingClientRect().top is 0, that is, it is up, although it works it gives me an error for undefined as seen in the console
this is my code
import { memo, useRef } from 'react';
import styles from '../styles/NotesToolbar.module.css';
import FilterSelect from './FilterSelect';
import NotesCounter from './NotesCounter';
const NotesToolbar = () => {
const toolbarRef = useRef();
window.addEventListener('scroll', () => {
if (toolbarRef.current.getBoundingClientRect().top <= 0) {
toolbarRef.current.classList.add(styles.ToolbarSticky);
} else {
toolbarRef.current.classList.remove(styles.ToolbarSticky);
}
});
return (
<div className={styles.Toolbar} ref={toolbarRef}>
<div className={styles.ToolbarLeft}>
<FilterSelect />
</div>
<div className={styles.ToolbarRight}>
<NotesCounter />
</div>
</div>
);
};
export default memo(NotesToolbar);
Few things about your code
First - you should have the event listener inside a useEffect and cleanup after the component unrenders or you will have tons of eventListeners
Nest - ref is defined (or assigned) to the dom element just before render. So ref will be undefined at first. A simple check if(ref.current) do_stuff will fix it.
useEffect(() => {
window.addEventListener('scroll', scrollHandler);
return(() => window.removeEventListener('scroll', scrollHandler);
}, [])
You can define the scrollHandler function inside or outside the effect (but if function is heavy, outside would be better)
const scrollHandler = () => {
if (toolbarRef.current) {
if (toolbarRef.current.getBoundingClientRect().top <= 0) {
toolbarRef.current.classList.add(styles.ToolbarSticky);
} else {
toolbarRef.current.classList.remove(styles.ToolbarSticky);
}
}
I've been studying react and developing an app, but i got a problem using context. In one component I create the context and provide its value, but when I try to use the current value of context in another component, I have the default value. Code:
Component One:
export const OwnerInformationContext = React.createContext({})
function NameChoose() {
...
const [ownerInformation,setOwnerInformation] = useState({})
function onpressSubmitButton(e : FormEvent) {
e.preventDefault();
...
setOwnerInformation({name:'name',roomId:'id',owner:'true'})
}
return(
<div className="page-container">
<OwnerInformationContext.Provider value={ownerInformation} />
...
<form onSubmit={onpressSubmitButton}>
...
</form>
...
);
}
export default NameChoose;
So when i try to use by:
import { OwnerInformationContext } from '../NameChoose/index'
function ComponentTwo(){
const consumeOwnerContext = useContext(OwnerInformationContext)
useEffect(() => {
console.log(consumeOwnerContext)
}, [])
return <h1>test</h1>
}
I got the default value provide in component one, that's {}.
It looks like your context provider is not actually wrapping any components, as it has a self-closing tag:
<OwnerInformationContext.Provider value={ownerInformation} />
It should be:
<OwnerInformationContext.Provider value={ownerInformation}>
{/* Your child components here will have access to the context */}
</OwnerInformationContext.Provider>
You are using useEffect as ComponentDidMount meaning only at start(mount) the value will be console log.
you should give consumeOwnerContext as a dependency to useEffect like this
useEffect(()=>{
console.log(consumeOwnerContext);
},[consumeOwnerContext]);
And rename consumeOwnerContext to consumeOwnerValue, because you are getting the value out of the context using useContext.
After that when you will click on submit button you should have ComponentTwo console log it.
import React, { useState, useEffect, useContext } from "react";
export const OwnerInformationContext = React.createContext({});
function ComponentTwo() {
const consumeOwnerContext = useContext(OwnerInformationContext);
useEffect(() => {
// You are using consumeOwnerContext inside useEffect, in that case add
// it as dependency if you want to see the updated consumeOwnerContext value
console.log(consumeOwnerContext);
}, [consumeOwnerContext]);
return <div>test</div>;
};
function NameChoose() {
const [ownerInformation, setOwnerInformation] = useState({});
function onpressSubmitButton(e) {
e.preventDefault();
setOwnerInformation({ name: "name",roomId: "id",owner: "true",});
}
return (
// The 'OwnerInformationContext.Provider' has to wrap the component
// that will use its context value. In your case, ComponentTwo
// has to be a child of NameChoose.
<OwnerInformationContext.Provider value={ownerInformation}>
<div className="page-container">
<form onSubmit={onpressSubmitButton}>
<button type="submit">Submit</button>
</form>
</div>
<ComponentTwo />
</OwnerInformationContext.Provider>
);
}
export default NameChoose;
I'm trying to close a popover that can only be closed via a close callback in its render props. I was wondering how I can use hooks or some other strategy to save this callback function between renders to call it in a useEffect. I tried using useContext to no avail: https://codesandbox.io/s/popover-close-from-content-y637f
You could use a ref to save the close function for use in useEffect. Here is a working codesandbox: https://codesandbox.io/s/popover-close-from-content-sgmgs
import React, { useEffect, useState, useRef } from "react";
import { Block } from "baseui/block";
import { Button } from "baseui/button";
import { StatefulPopover } from "baseui/popover";
export default () => {
const closeRef = useRef();
const [state, setState] = useState({ isSaving: false });
useEffect(() => {
if (state.isSaving) {
const timeout = setTimeout(() => {
console.log("closing", closeRef.current);
// close popover from here
closeRef.current && closeRef.current();
setState({ isSaving: false });
}, 5000);
return () => {
clearTimeout(timeout);
};
}
}, [state.isSaving]);
const onSave = () => {
console.log("save btn clicked");
setState({ isSaving: true });
};
return (
<div>
<StatefulPopover
content={(
{ close } // I need to call close per this library's API to close
) => {
closeRef.current = close;
return (
<Block padding="scale500" maxWidth="300px">
<Block paddingBottom="scale400">
content render prop is passed a <code>close()</code> callback so
it you can manually trigger popover close from within
</Block>
<Button isLoading={state.isSaving} onClick={onSave}>
Save
</Button>
</Block>
);
}}
>
<Button>Click Me</Button>
</StatefulPopover>
</div>
);
};
Context isn't working as you expect because you are attempting to access the context using useContext outside of the Provider. In order to access the value from the Provider, the useContext hooks must be utilized inside of a child component of the context Provider. Otherwise, the useContext will just get the default value passed into createContext.
I'm implementing a react-bootsrap carousel with react-redux and I'm getting the error in the title.
I'm using a controlled carousel and the error message appears when the carousel changes a slide automatically.
When the user clicks prev. next buttons and changes it manually all seems to be ok.
I don't get it should I add persist as props or options to props or similar?
Here's my code:
container:
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import store from 'store/configureStore'
import Slides from 'components/SlideShow'
import { getInitalSlides, handleSelect } from 'actions/SlidesActions'
class Home extends Component {
constructor(props) {
super(props)
this.state = {
index: null,
direction: null
}
this.handleSelect = this.handleSelect.bind(this)
static fetchData({ store }) {
return store.dispatch(getInitalSlides())
}
componentDidMount() {
this.props.getInitalSlides()
}
handleSelect(selectedIndex, e) {
//alert(e)
this.props.handleSelect(selectedIndex, e)
}
render() {
return (
<div className="Home">
<h1>Home Page</h1>
<Slides
slides={this.props.slides}
getInitialState={this.state.index}
getInitialStateD={this.state.direction}
slidesControl={this.handleSelect}
/>
<div><Link to="/question">to question</Link></div>
<div><Link to="/posts">to posts</Link></div>
</div>
)
}
}
function mapStateToProps (state) {
const { slides, handleSelect } = state
return { slides: state.slides, onSelect: state.handleSelect }
}
export { Home }
export default connect(mapStateToProps { getInitalSlides, handleSelect})(Home)
and here is the relevant bit in the component:
render() {
return (
<Carousel
activeIndex={this.props.getInitialState}
direction={this.props.getInitialStateD}
onSelect={(selectedIndex,e)=>this.props.slidesControl(selectedIndex,e)}
>
{
this.props.slides.map((s)=>{
let id = s.get('id')
let title = s.get('title')
let image = s.get('image')
let alt = s.get('alt')
let caption = s.get('caption')
return(
<Carousel.Item key={id} >
<img width={900} height={500} alt={s.get('alt')} src={image} alt={alt}/>
<Carousel.Caption>
<h3>{title}</h3>
<p>{caption}</p>
</Carousel.Caption>
</Carousel.Item>
)
})
}
</Carousel>)
}
}
Edit:
Here is the relevant react-bootstrap carousel code (where the error is thrown)
var onSelect = this.props.onSelect;
if (onSelect) {
if (onSelect.length > 1) {
// React SyntheticEvents are pooled, so we need to remove this event
// from the pool to add a custom property. To avoid unnecessarily
// removing objects from the pool, only do this when the listener
// actually wants the event.
e.persist();
e.direction = direction;
onSelect(index, e);
} else {
onSelect(index);
}
}
I analyzed Carousel.js code of react-bootstrap and I suspect it is issue in react-bootstrap library itself.
There is this line triggering change in Carousel.js code:
this.timeout = setTimeout(this.next, this.props.interval);
this.next method expects parameter of type SynteticEvent, but none is passed from setTimeout call. That exlpains your error message: ...persist of undefined....
The issue was probably hidden for a long time, but was exposed with this commit, where event parameter is actually used by Carousel.ja code itself.
So I recommend to create react-bootstrap Github issue and in the meantime downgrade to version that doesn't contain mentioned commit.
Here is the issue link in the project's github page. Seems there's a fix coming up:
https://github.com/react-bootstrap/react-bootstrap/issues/2029