I am now trying to use useTransition from react-spring.
But there's an invalid hook call error and I don't know why. (I've double-checked that react-dom and react version is the same.)
Also, my teacher uses const App()=>{} instead of function App(){}, and I want to know if they do the same thing.
This is my code.
import './App.css';
import {useState} from 'react';
import {useTransition, animated} from 'react-spring';
const App = () => {
const [isVisible, setIsVisible] = useState(false);
const transition = useTransition (isVisible, {
from: {x: -100, y: 800, opacity: 0},
enter: {x:0, y:0, opacity: 1},
leave:{},
});
return (
<div className="App">
<button onClick={()=>{
setIsVisible(v=>!v);
}}>
{isVisible ? 'unmount' : 'mount'}
</button>
<div className="container">
{transition((style, item) =>
item ? <animated.div style={style} className="item"/> : ''
)}
</div>
</div>
);
}
export default App;
Related
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
extend({ OrbitControls });
const Orbit = () => {
const { camera, gl } = useThree();
return <OrbitControls args={[camera, gl.domElement]} />;
};
function App() {
return (
<div style={{ height: "100vh", width: "100vw" }}>
<Canvas style={{ background: "black" }} camera={{ position: [3, 3, 3] }}>
<Orbit />
<axesHelper args={[5]} />
</Canvas>
</div>
);
}
This is the error I'm getting in the console
Uncaught TypeError: Class constructor OrbitControls cannot be invoked without 'new'
OrbitControls from three/examples/jsm/controls/OrbitControls is not for React Components.
#react-three/drei can help you.
Example
or
const { camera, gl } = useThree();
useEffect(
() => {
const controls = new OrbitControls(camera, gl.domElement);
return () => {
controls.dispose();
};
},
[camera, gl]
);
I have a React-Three-Fiber map project i'm working on, but running into a weird bug that I can't isolate.
On desktops the little map works perfectly, but once on Android, a transparent roughly 50(?)px size box in the middle of the viewport shows up and blocks and additional renderring in it until I pan the map past it.
Here's a video of what its doing:
https://youtu.be/4L1I9cZX1OM
Heres the code i'm using:
function App({moduleData}) {
const [floor, setFloor] = useState(1);
const [currentFloor, setCurrentFloor] = useState(floor);
const [riverwalkMap, setRiverwalkMap] = useState(moduleData.floor1.map_image.src);
const [currentPinSet, setCurrentPinSet] = useState('floor1');
const [pinInfo, setPinInfo] = useState()
const [zoomLevel, setZoomLevel] = useState(15);
const [pinHtml, setPinHtml] = useState("");
const [showMap, setShowMap] = useState(true);
const [pinHeader, setPinHeader] = useState("Unit: ");
const [open, setOpen] = useState(false);
const closeModal = () => setOpen(false);
function setPinColor(pinColor){
switch (pinColor){
case "green":
return 'pin_green.png'
case "red":
return 'pin_red.png'
case "yellow":
return 'pin_yellow.png'
default:
return 'pin_green.png'
}
}
function Scene({mapImage}){
const riverwalkMap = useLoader(TextureLoader, mapImage);
return(
<>
<mesh>
<planeGeometry args={[70,50]}/>
<meshBasicMaterial map={riverwalkMap} toneMapped={false}/>
</mesh>
</>
)
}
function Pin({props,pinInfo}){
const [active, setActive] = useState(0);
const [showPopup, setShowPopup] = useState(false);
const [hovered, setHovered] = useState(false);
useEffect(()=>{
document.body.style.cursor = hovered ? 'pointer' : 'auto'
},[hovered])
const { spring } = useSpring({
spring: active,
onChange: () => {
invalidate()
},
config: {mass:5, tension: 400, friction: 50, precision: 0.0001}
})
function returnPinClass(pin){
console.log('pin is: ' + pin);
switch (pin){
case 'available':
return '<span class="greenText">Available</span>';
default:
return '<span class="redText">Sold</span>';
}
}
function returnPinImage(pin){
console.log('pin image is: ' + pin);
return `<img src=${pin.src} alt=${pin.alt}/>`;
}
function setHtml(){
setPinHeader(`<h2>Unit: ${pinInfo.popup_title}</h2>`);
setPinHtml(`
<div class="popupContentBlock">
<div class="contentBlocks">
<div class="contentBlockLeft">
<div class="pdfViewer">
<iframe src="${pinInfo.pdf_file}"></iframe>
</div>
<div class="fractionalDiv">
Download PDF
</div>
</div>
</div>
</div>
`);
}
const scale = spring.to([0,1], [.6,1.25]);
const pinTexture = useLoader(TextureLoader, setPinColor(pinInfo.pin_color));
return(
<>
<a.mesh {...props}
scale-x={scale}
scale-y={scale}
scale-z={scale}
onPointerOver={(e)=> {
setActive(Number(!active));
}}
onPointerOut={(e)=>{
setActive(Number(!active));
}}
onClick={e => {
setHtml();
setOpen(o => !o);
// setShowMap(false);
}}
onPointerMissed={() => {setShowPopup(false)}}
position={[pinInfo.pin_position.x_pos,pinInfo.pin_position.y_pos,0]}
>
<planeGeometry args={[5,5]}/>
<meshBasicMaterial map={pinTexture} toneMapped={false} transparent={true}/>
</a.mesh>
</>
)
}
function setFloorButton(floor) {
setFloor(floor)
floorHeading(floor)
changePins(floor)
setCurrentFloor(floor)
}
function floorHeading(sentFloor) {
switch (sentFloor) {
case 1:
changeMap(moduleData.floor1)
return ReactHtmlParser(moduleData.floor1.heading);
case 2:
changeMap(moduleData.floor2)
return ReactHtmlParser(moduleData.floor2.heading);
case 3:
changeMap(moduleData.floor3)
return ReactHtmlParser(moduleData.floor3.heading);
case 4:
changeMap(moduleData.floor4)
return ReactHtmlParser(moduleData.floor4.heading);
default:
return 'No Floor Selected';
}
}
function changeMap(floorData) {
setRiverwalkMap(floorData.map_image.src);
}
function changePins(sentFloor){
setCurrentPinSet('floor'+sentFloor);
}
function closePop(){
setOpen(false);
}
function drawPins(currentSet){
switch (currentSet){
case 'floor1':
return moduleData.floor1.pins;
case 'floor2':
return moduleData.floor2.pins;
case 'floor3':
return moduleData.floor3.pins;
case 'floor4':
return moduleData.floor4.pins;
}
}
// THREE JS STUFF
// Drop Pins Programmatically
console.log(moduleData);
return (
<div className="cms-react-boilerplate__container">
<div className={"mapInfo"}>
<h1>Floor {currentFloor}</h1>
<p>Floors:</p>
<div className={"buttonSelector"}>
<button onClick={(e) => {
setFloorButton(1);
setPinHtml('');
}}>1</button>
<button onClick={(e) => {
setFloorButton(2);
setPinHtml('');
}}>2</button>
<button onClick={(e) => {
setFloorButton(3);
setPinHtml('');
}}>3</button>
<button onClick={(e) => {
setFloorButton(4);
setPinHtml('');
}}>4</button>
</div>
</div>
<div className={"mapGrid"}>
<div className={"mapDiv"} style={{ border: "2px solid black" }}>
<Canvas linear flat frameloop="demand" orthographic
camera={{position: [0, 0, 20], zoom: zoomLevel, up: [0, 0, 1], far: 10000}}
>
{showMap ? <Suspense fallback={null}>
{
drawPins(currentPinSet).map(e =>
<Pin pinInfo={e}/>
)}
<Scene mapImage={riverwalkMap}/>
</Suspense> : null}
<MapControls enableRotate={false}/>
</Canvas>
</div>
<div className={'infoLeft'} >
{!showMap ?
<div className={"infoGridBlock"}>
{ReactHtmlParser(pinHeader)}
<div className="closeButton" onClick={() => {
setShowMap(true);
setPinHtml('');
}}>
<p>✖</p>
</div>
</div>
: null }
<Popup open={open} closeOnDocumentClick onClose={closeModal} lockScroll={true}>
<div className={"modalBlock"} role="dialog">
<div className={"popupContentDiv"}>
<div className={"popupHeaderLeft"}>{ReactHtmlParser(pinHeader)}</div>
<div className={"popupHeaderRight"}><a onClick={closePop} aria-label="Close Popup">×</a></div>
</div>
{ReactHtmlParser(pinHtml)}
</div>
</Popup>
</div>
</div>
</div>
);
}
export default App;
What i've tried: I tried messing with some CSS but the closest i've gotten is if I force the React-Three-Fiber Canvas tag to have a unset height and width on mobile everything will render but no clickable elements will work.
Thank you for any help!
I am transferring my CRA to a Nextjs and I am having a bit of an issue with anything that uses the <canvas> element. The charts and data are mostly there, but my annotations are now missing from the charts. I have tried importing everything with the dynamic function for the parent element, but it still seems to not show the missing features.
I am also seeing some weird things happening on an arcgis map which is not visualizing 3d elements on a <canvas>. So my guess is that this has something with the way that canvas or d3 interact with the browser.
// parent component
import moment from 'moment-timezone';
import React, { useRef } from 'react';
import {
Chart as ChartJS,
LinearScale,
CategoryScale,
BarElement,
PointElement,
LineElement,
Legend,
Tooltip,
} from 'chart.js';
// import { Chart } from 'react-chartjs-2';
import { ArrowRight } from '../../icons/ArrowRight';
import Link from 'next/link';
import { chartOptions } from '../../lib/chartOptions';
import dynamic from 'next/dynamic';
const Chart = dynamic((): any => import('react-chartjs-2').then((m: any) => m.Chart), {
ssr: false,
});
ChartJS.register(
LinearScale,
CategoryScale,
BarElement,
PointElement,
LineElement,
Legend,
Tooltip,
);
export const MarkupCard = ({ item }: any) => {
const chartRef = useRef();
const userName = item.user_id.split('#')[0];
return (
<div className="w-2/3 pb-10 mx-auto border-2 border-blue items-center rounded-lg my-4 py-4 flex flex-row justify-between">
<div className="w-full text-left pl-4 pb-6 h-72">
<div className="w-full flex flex-row justify-between">
<h2 className="text-lg font-bold">{userName} Marked up a chart</h2>
<div className=" w-1/3 text-right pr-4">
<h2>
{moment(item.created_at)
.tz(process.env.NEXT_PUBLIC_TIMEZONE ?? '')
.format('MM-DD-YYYY hh:mm:ss a')}
</h2>
</div>
</div>
<h2>Route: {item.routeLongName}</h2>
<Chart
style={{ height: '100px', width: '99%' }}
ref={chartRef}
plugins={item.details.options.plugins}
className="trips-chart"
type="line"
options={chartOptions(item.details.options, item.details.annotations)}
data={item.details.chartData}
/>
</div>
<Link href={`/app/markupDetail/${item.id}`}>
<button className="mx-6 h-full flex">
<ArrowRight />
</button>
</Link>
</div>
);
};
// chart component
import React, { useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
import { supabase } from '../../client';
import { actions } from '../../store';
import { SocialNote } from '../../types';
import { Card } from './Card';
const SocialFeed = () => {
const [feed, setFeed] = useState<SocialNote[]>([]);
const dispatch = useDispatch();
const loadPage = async () => {
dispatch(actions.setLoaded(true));
const { data, error } = await supabase
.from('notes')
.select('*')
.order('last_update', { ascending: false });
if (data) {
setFeed(data);
console.log(data);
return data;
} else {
return error;
}
};
useEffect((): (() => void) => {
loadPage();
return () => supabase.removeAllSubscriptions();
}, []);
return (
<div className="w-full mx-auto overflow-y-auto">
{feed.map((item, key) => (
<Card key={key} item={item} />
))}
</div>
);
};
export default SocialFeed;
// chartoptions.js
export const chartOptions: any = (options: any, annotations: any) => {
const { title } = options;
const { tooltip } = options.plugins;
return {
title,
responsive: true,
maintainAspectRatio: false,
interaction: {
mode: 'index' as const,
intersect: false,
},
plugins: {
annotation: { annotations: annotations },
tooltip,
legend: {
position: 'top' as const,
},
title,
},
};
};
// next.config.js
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
module.exports = nextConfig
CRA
Nextjs
Turns out I just needed to register Annotations in ChartJS.register()
This was not the case for React, but was required for Nextjs
import Annotation from 'chartjs-plugin-annotation';
ChartJS.register(
Annotation,
LinearScale,
CategoryScale,
BarElement,
PointElement,
LineElement,
Legend,
Tooltip,
);
I am somewhat new to using useEffect and useRef. What I'm trying to do is create a content management system that enables scrollIntoView for n number of page elements from a database for a single page scrolling app.
I'm not able to get it to work so I'm hoping for some assistance.
I've posted a simple test where I have a functional react component where section 2 works (clicking the button scrolls down to the page element.
But my goal is to take 'n' sections from a database and create 'n' number of refs to scroll down to 'n' number of sections.
I tries useRef, useEffect, etc but I'm stumped. My code snippet shows a working example with manual ref declarations for Section 2 but Section 1 attempts to use a collection of Refs and that's not working
Here is a code example: https://codesandbox.io/embed/trusting-stallman-bsjj1?fontsize=14
import React, { useRef } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const App = () => {
let pageRef = useRef([
React.createRef(),
React.createRef()
]);
const pageHomeRef = React.createRef();
const scrollToRef = ref => ref.current.scrollIntoView({ behavior: "smooth" });
const scrollToPane = ref => scrollToRef(ref);
return (
<div className="App">
<div className="menu">
<button
onClick={() => {
scrollToPane(pageRef[1]);
}}
>
Scroll to Section 1
</button>
<button onClick={() => scrollToPane(pageHomeRef)}>
Section 2
</button>
</div>
<div className="page" style={{ marginTop: "1500px", marginBottom: "1500px" }}>
<div className="section1" ref={pageRef[1]}>
Section 1
</div>
<div className="section2" ref={pageHomeRef}>
Section 2
</div>
</div>
</div>
);
};
I'd like to feed an array of page elements and have the refs dynamically change as needed.
Little order the code - try it
You can use React.createRef() or useRef(null) in the array.
And make us many refs you want in array.
And even make map if you have a list (https://dev.to/ajsharp/-an-array-of-react-refs-pnf)
And you have other ways insted of refs.
import React, { useRef } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const App = () => {
let pageRef = [useRef(null),useRef(null)];
const pageHomeRef = [React.createRef(),React.createRef()];
const scrollToRef = ref => ref.current.scrollIntoView({ behavior: "smooth" });
const scrollToPane = num => scrollToRef(pageRef[num]);
return (
<div className="App">
<div className="menu">
<button
onClick={() => {scrollToPane(0)}}>Scroll to Section 1</button>
<button onClick={() => scrollToPane(1)}>Section 2</button>
</div>
<div
className="page"
style={{ marginTop: "1500px", marginBottom: "1500px" }}
>
<div className="section1" ref={pageRef[0]}>
Section 1
</div>
<div className="section2" ref={pageRef[1]}>
Section 2
</div>
</div>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
I'm using a resuable component for button wherein i wanna pass the color and bgColorvia props, color gets applied but then the background color doesnt apply
const useStyles = makeStyles(theme => ({
button: {
//width:'100%',
margin: theme.spacing(1)
},
input: {
display: "none"
}
}));
export default function ContainedButtons(props) {
const classes = useStyles();
const btnStyle = {
color: props.color,
backgroundColor: props.bgClrRed
};
console.log(props);
return (
<div>
<Button
variant="contained"
style={{ backgroundColor: props.bgClrRed, color: props.color }}
fullWidth="true"
className={classes.button}
>
{props.name}
</Button>
<Button
variant="contained"
style={btnStyle}
fullWidth="true"
className={classes.button}
>
{props.name}
</Button>
</div>
);
}
I'm missing something I don't know what can anyone please lemme know
Updates
import ContainedButtons from '../container/buttonsControl';
import css from '../variable.scss';
Try a spread operator:
style={...btnStyle}