Wav sound is not playing in react - reactjs

I'm getting the error "Uncaught (in promise) DOMException: The media resource indicated by the src attribute or assigned media provider object was not suitable.", while trying to play a wav sound file using react-sound and "Uncaught (in promise) DOMException: The buffer passed to decodeAudioData contains an unknown content type." in a three.js scene using a positionalAudio. It works when I use mp3 files. I already tried to fix it by importing the wav file through file-loader and a webpack config. On the dev and build server everything works also using wav files but after deplyoing to a cloudflare server I'm getting this error when I try to use wav.
Now my second guess is, that I somehow have to set to code up using a promise but I am struggling as how to do it.
Code for react-sound
import Sound from 'react-sound'
import wavURL from '../../../public/sounds/ambientStereoSound.wav'
export default function AmbientSound(props) {
let state = ''
if(props.state){
state = Sound.status.PLAYING
}else{
state = Sound.status.PAUSED
}
return (
<Sound
url={wavURL}
autoLoad={true}
playStatus={state}
loop={true}
volume={100}
/>
)
}
Code for three.js (react-three-fiber)
import * as THREE from 'three'
import React, { Suspense, useMemo, useEffect, useState } from 'react'
import { useThree, useLoader } from '#react-three/fiber'
import { PositionalAudioHelper } from 'three/examples/jsm/helpers/PositionalAudioHelper.js'
import { useControls } from 'leva'
function PositionalAudio({ refs, url, volume, rolloffFactor, coneOuterGain, state }) {
const sound = refs
const { camera } = useThree()
const [listener] = useState(() => new THREE.AudioListener())
const buffer = useLoader(THREE.AudioLoader, url)
useEffect(() => {
sound.current.setBuffer(buffer)
sound.current.setRefDistance(1)
sound.current.setRolloffFactor(1)
sound.current.setDirectionalCone(180, 260, 0)
sound.current.setLoop(true)
sound.current.setVolume(volume)
sound.current.play()
const helper = new PositionalAudioHelper(sound.current)
sound.current.add(helper)
camera.add(listener)
return () => camera.remove(listener)
}, [])
useEffect(() => {
sound.current.setDirectionalCone(180, 260, coneOuterGain)
sound.current.setRolloffFactor(rolloffFactor)
sound.current.setVolume(volume)
}, [rolloffFactor, volume, coneOuterGain])
if(state) {
useEffect(() => {
sound.current.play()
}, [state])
}else{
useEffect(() => {
sound.current.pause()
}, [state])
}
return <positionalAudio ref={sound} args={[listener]} />
}
type SoundObject = {
id: number
x: number
y: number
z: number
position: number[]
filePath: string
name: string
rotation: number
}
type SoundObjectProps = {
soundObjects: SoundObject[]
}
export default function SoundObject(props: SoundObjectProps) {
const audioRefs = useMemo(
() =>
Array(props.soundObjects.length)
.fill(0)
.map(() => React.createRef()),
[]
)
const PositionalSoundObject = props.soundObjects.map((soundObject, index) => {
const name = soundObject.name
const { Rotation, Volume, Rolloff, X, Y, Z, ConeOuterGain } = useControls( name, {
Rotation: {
value: soundObject.rotation,
min: 0,
max: Math.PI * 2,
step: Math.PI * 0.25
},
Volume: {
value: 1,
min: 0,
max: 1,
step: 0.05
},
Rolloff: {
value: 1,
min: 0,
max: 1,
step: 0.05
},
ConeOuterGain: {
value: 0,
min: 0,
max: 1
},
X: {
value: soundObject.x,
},
Y: {
value: soundObject.y,
},
Z: {
value: soundObject.z,
}
})
return (
<mesh position={[X, Y, Z]} rotation={[0, Rotation, 0]}>
<sphereGeometry args={[0.1, 8, 8]} />
<meshStandardMaterial color='hotpink' wireframe />
<PositionalAudio
refs={audioRefs[index]}
volume={Volume}
rolloffFactor={Rolloff}
url={soundObject.filePath}
key={soundObject.id}
coneOuterGain={ConeOuterGain}
state={props.state}
/>
</mesh>
)
})
return <Suspense fallback={null}>{PositionalSoundObject}</Suspense>
}

Not exactly sure why, but hosting the wav files on the server and requesting it through https fixed the problem. My guess is that next.js (which runs node.js) can't handle loading wav files from the public folder out of the box and that it is not a problem related to react.

Related

React - Map single field from array to array issue

I found this nice implementation for a basic card game
It is based on this (however slightly different):
https://react-spring.io/hooks/use-springs#usesprings < doc
https://codesandbox.io/s/github/pmndrs/react-spring/tree/master/demo/src/sandboxes/cards-stack < doc example code
So here's the issue:
It has two arrays
cards which stores the index of cards (hardcoded)
cardData which stores the contents of cards (hardcoded)
What I'm trying to do is bind array 1 dynamically based on cardData.id
This does semi-works, it compiles and you can swipe the cards. However when all cards have cleared the board it wont reset as it would with the card-coded cards.
import React, { useState, useEffect } from "react";
import { useSprings } from "react-spring";
import { useGesture } from "react-with-gesture";
import Card from "./Card";
const cardData = [
{
id: 1,
question: "Islamic finance doesnt have different requirements",
pic:"https://images.unsplash.com/photo-1519817650390-64a93db51149?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=627&q=80",
text:
"Check out week 5 documents",
correct: false,
value: 15
},
{
id: 2,
question: "CEO requirements",
pic:
"https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fdoerlife.com%2Fwp-content%2Fuploads%2F2020%2F03%2FSP.png&f=1&nofb=1",
text: "They must decide high-level policy and strategy",
correct: true,
value: 6
},
{
id: 3,
question: "The sky is green",
text: "Make sure to look outside!",
correct: false,
value: 2
}
,
{
id: 4,
question: "This signifies British currency",
pic: "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fwww.kindpng.com%2Fpicc%2Fm%2F112-1123896_black-pound-sterling-symbol-clipart-pound-sign-hd.png&f=1&nofb=1",
text:
"Maybe check in your wallet",
correct: true,
value: 17
}
];
const cards = [1, 2, 3, 4];
const to = i => ({
x: 0,
y: i * -12,
scale: 1,
rot: -10 + Math.random() * 20,
delay: i * 150
});
const from = i => ({ rot: 0, scale: 1.5, y: -1000 });
const trans = (r, s) =>
`perspective(1500px) rotateX(15deg) rotateY(${r /
10}deg) rotateZ(${r}deg) scale(${s})`;
function Swipe() {
console.log(cardData)
// const [cards, setCards] = useState([]);
// useEffect( () => {
// cardData.map(({id}) => {
// setCards(prev => [...prev, id]) // this doesnt reset cards after sorting all
// })
// },[])
const [gone] = useState(() => new Set());
const [props, set] = useSprings(cards.length, i => ({
...to(i),
from: from(i)
}));
const bind = useGesture(
(
{
args: [index],
down,
delta: [xDelta],
distance,
direction: [xDir],
velocity
}) => {
const trigger = velocity > 0.2;
const dir = xDir < 0 ? -1 : 1;
if (!down && trigger) gone.add(index);
set(i => {
if (index !== i) return;
const isGone = gone.has(index);
if (isGone){
console.log("index",i)
console.log("isgone",isGone) // grab by is gone
console.log("cards",cards)
// set()
}
const x = isGone ? (200 + window.innerWidth) * dir : down ? xDelta : 0;
const rot = xDelta / 100 + (isGone ? dir * 10 * velocity : 0);
const scale = down ? 1.1 : 1;
return {
x,
rot,
scale,
delay: undefined,
config: { friction: 50, tension: down ? 800 : isGone ? 200 : 500 }
};
});
if (!down && gone.size === cards.length)
setTimeout(() => gone.clear() || set(i => to(i)), 600);
// insert game end here
}
);
return (
<div className="swipe">
{props.map(({ x, y, rot, scale }, i) => (
<Card i={i} x={x} y={y} rot={rot} scale={scale} trans={trans} cardData={cardData} bind={bind} key={i}/>
))};
</div>);
}
export default Swipe;
Here is a live example to make it more legible: https://codesandbox.io/s/wandering-lake-iwzns5?file=/src/App.js
Any suggestions are welcome!
Turns out the impl I found which was a little different from the docs, for some reason had two separate arrays when it was unneeded. Changing instances ofcards into cardData seems to work fine.

Nivo line chart custom mesh layer

I have nivo line chart with gaps like this:
Gaps are covered by passing y/value: null in november and december in data series
Tooltip displays only on data points and this is correct, but I want add tooltip at November and December with explanation why there is no data.
The solution is to add custom layer 'mesh' which is responsible for displaying tooltips on line chart.
You have to declare custom layers in <ResponsiveLine component:
layers={[
'grid',
'markers',
'axes',
'areas',
'crosshair',
'lines',
'slices',
'points',
CustomMesh,
'legends',
]}
Create CustomMesh component:
const CustomMesh = (layerData: any) => {
const { showTooltipAt, hideTooltip } = useTooltip();
const handleMouseEnter = (point: any) => {
showTooltipAt(
layerData.tooltip({ point }),
[point.x + layerData.margin.left, point.y + layerData.margin.top],
'top'
);
};
const handleMouseMove = (point: any) => {
showTooltipAt(
layerData.tooltip({ point }),
[point.x + layerData.margin.left, point.y + layerData.margin.top],
'top'
);
};
const handleMouseLeave = (point: any) => {
hideTooltip();
};
const nullValuePoints = layerData.series.reduce((acc: any[], cur: any) => {
cur.data.forEach(({ data, position }: any) => {
if (data.y === null) {
const point = {
x: position.x,
y: 100, //whatever you want
data: {
x: data.x,
},
};
acc.push(point);
}
});
return acc;
}, []);
return (
<Mesh
nodes={[...layerData.points, ...nullValuePoints]}
width={layerData.width}
height={layerData.height}
onMouseEnter={handleMouseEnter}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
debug={layerData.debugMesh}
/>
);
};
When nullValuePoints are my custom points with no data
Import required packages:
import { Mesh } from '#nivo/voronoi';
import { useTooltip } from '#nivo/tooltip';
result:

Lightning JS Chart causing crashes and not showing data correctly

I have a component that I want to show a graph with multiple line series representing price changes over the last 24 hours. I have an endpoint that sends this data and I use the code below to show it.
One of the issues comes from errors seeming to come from the library itself meaning the graph will not even show up. Errors from the console when I load the page.
Other times, the page will load for a second and then go white and drain enough CPU to cause a crash.
The few times that the graph actually shows up on screen, it does not show any lines until the lines 81-85 are uncommented which it then shows the lines but does not zoom in on them leaving a mess on the screen.
Any help would be much appreciated.
/* eslint-disable new-cap */
/* eslint-disable #typescript-eslint/no-unused-vars */
/* eslint-disable no-magic-numbers */
import React, { useEffect, useState } from "react";
import { LegendBoxBuilders, lightningChart, Themes } from "#arction/lcjs";
import "./TopCurrencyGraph.css";
import axios from "axios";
export interface data {
data: dataPoint[];
}
export interface dataPoint {
currency: string;
percentage: number;
timestamp: string;
}
interface graphPoint {
x: number;
y: number;
}
const TopCurrencyGraph = () => {
const historicalAddr = `http://${
process.env.back || "localhost:8000"
}/historical24hChangeData`;
useEffect(() => {
const map: { [name: string]: graphPoint[] } = {};
axios
.get(historicalAddr)
.then((res) => {
const { points } = res.data;
const pointList = points as dataPoint[];
pointList.forEach((obj) => {
const newPoint = {
x: new Date(obj.timestamp).getTime() * (60 * 24),
y: obj.percentage * 100,
};
if (obj.currency in map) {
map[obj.currency].push(newPoint);
} else {
map[obj.currency] = [newPoint];
}
});
})
.catch((err) => {
console.log(err, historicalAddr);
});
const chart = lightningChart().ChartXY({
theme: Themes.lightNew,
container: "currency-graph",
});
chart.setTitle("Top Currencies");
chart.getDefaultAxisX().setTitle("Time");
chart.getDefaultAxisY().setTitle("Percentage Change");
const entries = Object.entries(map);
const names = entries.map(([a, _b]) => a);
const lists = entries.map(([_, b]) => b);
const seriesArray = new Array(5).fill(null).map((_, idx) =>
chart
.addLineSeries({
dataPattern: {
pattern: "ProgressiveX",
},
})
// eslint-disable-next-line arrow-parens
.setStrokeStyle((stroke) => stroke.setThickness(1))
.setName(names[idx])
);
seriesArray.forEach((series, idx) => {
if (idx === 1) {
series.add(lists[idx]);
}
});
chart.addLegendBox(LegendBoxBuilders.HorizontalLegendBox).add(chart);
return () => {
chart.dispose();
};
}, []);
// done thnx
return (
<div className="graph-container">
<div id="currency-graph" className="graph-container"></div>
</div>
);
};
export default TopCurrencyGraph;
Your code looks syntax wise correct, but I believe you are running into issues due to not managing asynchronous code (axios getting data from your endpoint) properly.
const map: { [name: string]: graphPoint[] } = {};
axios
.get(historicalAddr)
.then((res) => {
// This code is NOT executed immediately, but only after some time later.
...
})
// This code and everything below is executed BEFORE the code inside `then` block.
// Because of this, you end up supplying `undefined` or other incorrect values to series / charts which shows as errors.
const chart = lightningChart().ChartXY({
theme: Themes.lightNew,
container: "currency-graph",
});
You might find it useful to debug the values you supply to series, for example like below. I think the values are not what you would expect.
seriesArray.forEach((series, idx) => {
if (idx === 1) {
console.log('series.add', lists[idx])
series.add(lists[idx]);
}
});
Improvement suggestion
Here's my attempt at modifying the code you supplied to manage the asynchronous data loading correctly, by moving all code that relies on the data after the data is processed.
/* eslint-disable new-cap */
/* eslint-disable #typescript-eslint/no-unused-vars */
/* eslint-disable no-magic-numbers */
import React, { useEffect, useState } from "react";
import { LegendBoxBuilders, lightningChart, Themes } from "#arction/lcjs";
import "./TopCurrencyGraph.css";
import axios from "axios";
export interface data {
data: dataPoint[];
}
export interface dataPoint {
currency: string;
percentage: number;
timestamp: string;
}
interface graphPoint {
x: number;
y: number;
}
const TopCurrencyGraph = () => {
const historicalAddr = `http://${
process.env.back || "localhost:8000"
}/historical24hChangeData`;
useEffect(() => {
const chart = lightningChart().ChartXY({
theme: Themes.lightNew,
container: "currency-graph",
});
chart.setTitle("Top Currencies");
chart.getDefaultAxisX().setTitle("Time");
chart.getDefaultAxisY().setTitle("Percentage Change");
const seriesArray = new Array(5).fill(null).map((_, idx) =>
chart
.addLineSeries({
dataPattern: {
pattern: "ProgressiveX",
},
})
// eslint-disable-next-line arrow-parens
.setStrokeStyle((stroke) => stroke.setThickness(1))
);
chart.addLegendBox(LegendBoxBuilders.HorizontalLegendBox).add(chart);
axios
.get(historicalAddr)
.then((res) => {
const { points } = res.data;
const pointList = points as dataPoint[];
const map: { [name: string]: graphPoint[] } = {};
pointList.forEach((obj) => {
const newPoint = {
x: new Date(obj.timestamp).getTime() * (60 * 24),
y: obj.percentage * 100,
};
if (obj.currency in map) {
map[obj.currency].push(newPoint);
} else {
map[obj.currency] = [newPoint];
}
});
const entries = Object.entries(map);
const names = entries.map(([a, _b]) => a);
const lists = entries.map(([_, b]) => b);
seriesArray.forEach((series, idx) => {
series.setName(names[idx])
if (idx === 1) {
series.add(lists[idx]);
}
});
})
.catch((err) => {
console.log(err, historicalAddr);
});
return () => {
chart.dispose();
};
}, []);
// done thnx
return (
<div className="graph-container">
<div id="currency-graph" className="graph-container"></div>
</div>
);
};
export default TopCurrencyGraph;

Use React Spring With Orbit Controls in React Three Fiber

I'm trying to use Orbitcontrols in combination with react spring to animate my camera in React Three Fiber. This is my approach so far:
function Controls({ cameraData, duration }) {
const [orbit, setOrbit] = useState(true);
const [target, setTarget] = useState(cameraData.lookAt);
const { gl, camera } = useThree();
const springProps = useSpring({
config: { duration: duration ? duration : 1000, easing: easings.easeCubic },
from: {
x: camera.position.x - 0.1,
y: camera.position.y - 0.1,
z: camera.position.z - 0.1,
lookAtX: camera.lookAt.x - 0.1,
lookAtY: camera.lookAt.y - 0.1,
lookAtZ: camera.lookAt.z - 0.1,
},
to: {
x: cameraData.position[0],
y: cameraData.position[1],
z: cameraData.position[2],
lookAtX: cameraData.lookAt[0],
lookAtY: cameraData.lookAt[1],
lookAtZ: cameraData.lookAt[2],
},
onStart: (ya) => {
setOrbit(false);
},
onRest: (ya) => {
setOrbit(true);
setTarget(cameraData.lookAt)
},
});
useFrame((state, delta) => {
if (!orbit) {
camera.position.x = springProps.x.animation.values[0]._value;
camera.position.y = springProps.y.animation.values[0]._value;
camera.position.z = springProps.z.animation.values[0]._value;
camera.lookAt(
springProps.lookAtX.animation.values[0]._value,
springProps.lookAtY.animation.values[0]._value,
springProps.lookAtZ.animation.values[0]._value
);
}
});
return (
<OrbitControls
enabled={orbit}
target={target}
args={[camera, gl.domElement]}
/>
);
}
I disable OrbitControls when my Spring starts. Everything works.
But: When using OrbitControl my camera position changes. After that, when I start my Spring Animation the 'from' values are not updated.
For example I tween from x: 100 to x: 500. Then Rotate my Camera via OrbitControls to x: 700. When I start my next Spring Animation it animates starting from x: 500 instead of x: 700.
How can I update my from values.
Thanks in regard
It seems there are several conversations around not animating the camera such as the one found at https://github.com/pmndrs/react-three-fiber/discussions/505#discussioncomment-3120683 I post there an approach I did using someone else idea to animate the composition and make the illusion of a camera animation, that mindset shift can be the key for this use case.
Basically you have a wrapper that moves the entire composition to the focus of the screen to pretend the camera has moved.
The main part is the component below:
const AnimatedGroup = ({ children }: { children: React.ReactNode }) => {
const [focusPoint, setFocusPoint] = useState({
from: [0, -3, -100],
to: [0, 0, 0],
})
const { position } = useSpring({
position: focusPoint.to,
from: { position: focusPoint.from },
})
const newPosition = position as unknown as Vector3
const handleOnClick = (e: ThreeEvent<MouseEvent>) => {
const objectPosition = e.object.position.toArray()
const newFocusPoint = {
from: [focusPoint.to[0], focusPoint.to[1], focusPoint.to[2]],
to: [objectPosition[0] * -1, objectPosition[1], objectPosition[2] * -1],
}
if (!e.object.userData.pitstopVariant) return
setFocusPoint(newFocusPoint)
}
return (
<animated.group position={newPosition} onClick={handleOnClick}>
{children}
</animated.group>
)
}

React useEffect doesn't change data displayed on map

I'm playing with uber's react-map-gl and deck-gl libraries to try to display data dynamically.I've got 2 components in my react little app.A navigation bar and a Mapbox map.So here is my pipeline.When the page first loads,only the map is displayed without any marker or visual data.But when i click on one of navigation bar link,an action creator gets called,when i make an ajax call to fetch some data,and from the action that is dispatched a pass my response data as payload and the reducer is reached so that i have a new version of the store.the data that i would like to visualize in they stor key : mainProjects that contains an array of geojson.My click on a navbar link succefully updates that value,and in the actual Map component,i can load the new values but useEffect does not update my localstate.Here is my map code:
import React, { useState, useEffect, useContext } from "react";
import { StaticMap } from "react-map-gl";
import { MapContext } from "./contexts/MapProvider";
import DeckGL, { GeoJsonLayer } from "deck.gl";
import chroma from "chroma-js";
import { connect } from "react-redux";
const MAPBOX_TOKEN =
"pk.mykey";
const mapStyle = "mapbox://mymapstyle";
function getEnergyFillColor(regime) {
const ENERGY_COLORS = {
naturalGaz: "#FF8500",
coal: "#99979A",
nuclear: "#E0399E",
hydroelectric: "#0082CB",
Wind: "#00B53B",
solar: "#DBCA00",
oil: "#FF0009",
other: "#FFEFD3"
};
let color;
switch (regime) {
case "Hydraulique":
color = ENERGY_COLORS.hydroelectric;
break;
case "Thermique":
color = ENERGY_COLORS.nuclear;
break;
default:
color = ENERGY_COLORS.other;
break;
}
color = chroma(color)
.alpha(0.667)
.rgba();
color[3] *= 255;
return color;
}
function _onClick(info) {
if (info.object) {
// eslint-disable-next-line
alert(
`${info.object.properties.NOM} (${info.object.properties.PROVINCE}) - ${
info.object.properties.PUISSANCE
}MW`
);
}
}
function Map({ mainProjects }) {
const { viewport, setViewport, onLoad } = useContext(MapContext);
const [airports, setAireports] = useState();
const [electricalEnergy, setElectricalEnergy] = useState();
const [hospitals, setHospitals] = useState();
const [roads, setRoads] = useState();
useEffect(() => {
if (mainProjects.length) {
setHospitals(mainProjects[0].hospitals);
setAireports(mainProjects[1].aeroports);
setElectricalEnergy(mainProjects[2].electricite);
setRoads(mainProjects[2].routes);
}
}, [airports, electricalEnergy, hospitals, roads]);
const layers = [
//ENERGIE ELECTRIQUE
new GeoJsonLayer({
id: "energy",
data: electricalEnergy,
// Styles
filled: true,
pointRadiusMinPixels: 20,
opacity: 1,
pointRadiusScale: 2000,
getRadius: energyItem => energyItem.properties.puissance * 3.14,
getFillColor: energyItem =>
getEnergyFillColor(energyItem.properties.regime),
// Interactive props
pickable: true,
autoHighlight: true,
onClick: _onClick
}),
//AEROPORTS
new GeoJsonLayer({
id: "airports",
data: airports,
// Styles
filled: true,
pointRadiusMinPixels: 20,
opacity: 1,
pointRadiusScale: 2000,
getRadius: energyItem => energyItem.properties.PUISSANCE * 3.14,
getFillColor: energyItem =>
getEnergyFillColor(energyItem.properties.REGIME),
// Interactive props
pickable: true,
autoHighlight: true,
onClick: _onClick
}),
//HOSPITALS
new GeoJsonLayer({
id: "hospitals",
data: hospitals,
// Styles
filled: true,
pointRadiusMinPixels: 20,
opacity: 1,
pointRadiusScale: 2000,
getRadius: energyItem => energyItem.properties.PUISSANCE * 3.14,
getFillColor: energyItem =>
getEnergyFillColor(energyItem.properties.REGIME),
// Interactive props
pickable: true,
autoHighlight: true,
onClick: _onClick
}),
//ROUTES
new GeoJsonLayer({
id: "roads",
data: roads,
pickable: true,
stroked: false,
filled: true,
extruded: true,
lineWidthScale: 20,
lineWidthMinPixels: 2,
getFillColor: [160, 160, 180, 200],
getLineColor: d => [255, 160, 20, 200],
// getLineColor: d => colorToRGBArray(d.properties.color),
getRadius: 100,
getLineWidth: 1,
getElevation: 30,
onHover: ({ object, x, y }) => {
// const tooltip = object.properties.name || object.properties.station;
/* Update tooltip
http://deck.gl/#/documentation/developer-guide/adding-interactivity?section=example-display-a-tooltip-for-hovered-object
*/
},
onClick: _onClick
})
];
return (
<>
<link
href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.0/mapbox-gl.css"
rel="stylesheet"
/>
<DeckGL
initialViewState={viewport}
viewState={viewport}
controller={true}
layers={layers}
onLoad={onLoad}
onViewportChange={nextViewport => setViewport(nextViewport)}
>
<StaticMap mapboxApiAccessToken={MAPBOX_TOKEN} mapStyle={mapStyle} />
</DeckGL>
</>
);
}
const mapStateToProps = ({
selectedLinks: { sectorSelected, provinceSelected, subSectorSelected },
mainProjects
}) => {
if (sectorSelected || provinceSelected || subSectorSelected) {
return {
mainProjects
};
} else {
return {
mainProjects: []
};
}
};
export default connect(mapStateToProps)(Map);
In the above code,i try to update my local state values by is setters,but useEffect doesn't seem to work.And it looks like it's only called once,at when the component renders for the first time.How can i solve this problem?
Thank you!!
Your useEffect has a set of dependencies that donˋt match those, which are actually used.
You are setting your local state with elements of mainProjects, so useEffect will only do something when mainProjects changes.
You donˋt seem to be doing anything with your useState-Variables, so you donˋt change state, so react doesnˋt rerender.
Update: it is really important to check, that the dependency-array (2nd argument to useEffect) and the used variables inside the function (1st argument) correspond, else bad things will happen ;-)
There is an eslint-rule for that: https://www.npmjs.com/package/eslint-plugin-react-hooks

Resources