gpt4 book ai didi

javascript - React props 的变化超出预期

转载 作者:行者123 更新时间:2023-11-28 14:13:12 24 4
gpt4 key购买 nike

我有一个 React 应用程序,当它感知到 API 命中时,它会传递到 SlotMachine 组件(使用 Pusher 进行发布-订阅)。

它应该只 rotate() 每次 API 命中一次,但是,正如您在我的输出中看到的,它会调用 rotate() <多次并表示每次之前 Prop 都已更改。但这些 Prop 在控制台中看起来是一样的,并且在第一个 API 之后没有更多的 API 命中(我正在使用 Postman 触发)。

有什么原因让我的 Prop 发生如此大的变化吗?我对钩子(Hook)或 Prop 有什么不明白的地方?另外,为什么我的旋转函数会不断被调用,除非在第一个 API 命中之后?

应用程序:

import React, { useState, useEffect } from 'react'
import { render } from 'react-dom'
import Pusher from 'pusher-js'
import SlotMachine from './components/SlotMachine'

const App = () => {
const [ slots, setSlots ] = useState([]);
const [ apiHit, setApiHit ] = useState(false);

const pusher = new Pusher('XXXXXXX', {
cluster: 'XXX',
encrypted: true
});

const channel = pusher.subscribe('my-channel');
channel.bind('my-event', data => {
console.log(`Got data from pusher ${data}`);
setSlots(data);
setApiHit(true);
});

return(
<div>
<SlotMachine slots={slots} apiHit={apiHit}/>
</div>
);
};

render(<App />, document.getElementById('root'));

老虎机:

 import React, { useEffect, useRef, useState } from 'react'
import './slots.css'

function rnd(min, max) {
return Math.floor(Math.random() * (max - min)) + min
}

const SlotMachine = (props) => {
const ringElements = useRef();
const [manual, setManual] = useState(true);
const [rings, updateRings] = useState([]);
const [ slots, setSlots ] = useState([]);

const slotMap = {
0: 72,
1: 144,
2: 216,
3: 288,
4: 360
};

useEffect(()=>{
console.log(' --- props change --- ');
console.log(props);
setSlots( slots => props.slots );
if(props.slots !== undefined && props.apiHit === true ) {
setManual(manual => false);
rotate();
setManual(true);
}
}, [props.slots, props.apiHit]);

//need to store previous to get accurate measure
const rotate = () => {
console.log(`---ROTATE---`);
rings.forEach((el, i) => {
let obj = el; //should be an obj
console.log(obj);
let prev = null;
if (obj.prev !== null) { prev = obj.prev; } //update prev if not first time
console.log(`Prev is ${prev}`);
let element = obj.ringElement; //should be the ring itself
//let obj = rings[i];
console.log(element);
//get the slots it needs to move to
let move = manual && !props.apiHit ? slotMap[rnd(0,4)] : slotMap[slots[i]];
console.log(`move: ${move}`);
let diff = Math.abs(prev - move);
console.log(`The diff is ${diff}`);
//take the previous and the move and figure out "difference", be sure to add that difference to the spin
let res = move + (360 * rnd(3,6));
//let res = move //+ (360 * rnd(3,6)); //randomly spin should end up back at same spot no matter what
console.log(`rotateX(${res}deg) for ring${i}`);
element.style.transform = `rotateX(${res}deg)`;
obj.prev = move;
//rings[i] = obj;// update proper object in state
rings[i] = obj;
updateRings( rings );
});
}

//when first mounts
useEffect(() => {
console.log('component did mount');
Array.from(ringElements.current.children).forEach((el, i) => {
console.log(`elements in ring: ${el}`);
let obj = {}
obj.ringElement = el
obj.prev = null
updateRings(rings => [...rings, obj])
// updateRings(rings => [...rings, el]);
});
}, []);

return(
<div>
<div className="slots">
<div className="rings" ref={ringElements}>
<div className="ring">
<div className="slot" id="0">0</div>
<div className="slot" id="1">1</div>
<div className="slot" id="2">2</div>
<div className="slot" id="3">3</div>
<div className="slot" id="4">4</div>
</div>
<div className="ring">
<div className="slot" id="0">0</div>
<div className="slot" id="1">1</div>
<div className="slot" id="2">2</div>
<div className="slot" id="3">3</div>
<div className="slot" id="4">4</div>
</div>
<div className="ring">
<div className="slot" id="0">0</div>
<div className="slot" id="1">1</div>
<div className="slot" id="2">2</div>
<div className="slot" id="3">3</div>
<div className="slot" id="4">4</div>
</div>
</div>
</div>
<button className="spin-button" onClick={() => { setManual(true); rotate(); } }>SPIN</button>
</div>

);
}

export default SlotMachine

输出:

初始 API 命中(按预期工作,触发 Rotate() 一次

Got data from pusher 3,1,3 .   <-- new API data recieved 
55 **--- props change ---**
56 {slots: Array(3), apiHit: false}
55 **--- props change ---**is
56 {slots: Array(3), apiHit: true}
71 **---ROTATE---**
75 {ringElement: div.ring, prev: null}
83 Prev is null
87 <div class=​"ring" style=​"transform:​ rotateX(2088deg)​;​">​…​</div>​
90 move: 288
92 The diff is 288
96 rotateX(2088deg) for ring0
75 {ringElement: div.ring, prev: null}
83 Prev is null
87 <div class=​"ring" style=​"transform:​ rotateX(1224deg)​;​">​…​</div>​
90 move: 144
92 The diff is 144
96 rotateX(1224deg) for ring1
75 {ringElement: div.ring, prev: null}
83 Prev is null
87 <div class=​"ring" style=​"transform:​ rotateX(2088deg)​;​">​…​</div>​
90 move: 288
92 The diff is 288
96 rotateX(2088deg) for ring2

后续 API 命中会执行多次旋转调用,并显示每次调用之前的 Prop 更改。

Got data from pusher 3,0,1 . <-- new API hit 
55 --- props change ---
56 {slots: Array(3), apiHit: true}
71 ---ROTATE---
75 {ringElement: div.ring, prev: 288}
83 Prev is 288
87 <div class=​"ring" style=​"transform:​ rotateX(2088deg)​;​">​…​</div>​
90 move: 288
92 The diff is 0
96 rotateX(1368deg) for ring0
75 {ringElement: div.ring, prev: 144}
83 Prev is 144
87 <div class=​"ring" style=​"transform:​ rotateX(1224deg)​;​">​…​</div>​
90 move: 144
92 The diff is 0
96 rotateX(1584deg) for ring1
75 {ringElement: div.ring, prev: 288}
83 Prev is 288
87 <div class=​"ring" style=​"transform:​ rotateX(2088deg)​;​">​…​</div>​
90 move: 288
92 The diff is 0
96 rotateX(2088deg) for ring2
VM12097 index.js:39 Got data from pusher 3,0,1 . <-- **same** API hit but recorded again????
55 --- props change ---
56 {slots: Array(3), apiHit: true}apiHit: trueslots: (3) [3, 0, 1]__proto__: Object
71 ---ROTATE---
75 {ringElement: div.ring, prev: 288}
83 Prev is 288
87 <div class=​"ring" style=​"transform:​ rotateX(2088deg)​;​">​…​</div>​
90 move: 288
92 The diff is 0
96 rotateX(1368deg) for ring0
75 {ringElement: div.ring, prev: 144}
83 Prev is 144
87 <div class=​"ring" style=​"transform:​ rotateX(1224deg)​;​">​…​</div>​
90 move: 72
92 The diff is 72
96 rotateX(1152deg) for ring1
75 {ringElement: div.ring, prev: 288}
83 Prev is 288
87 <div class=​"ring" style=​"transform:​ rotateX(2088deg)​;​">​…​</div>​
90 move: 144
92 The diff is 144
96 rotateX(1584deg) for ring2
VM12097 index.js:39 Got data from pusher 3,0,1
55 --- props change ---
56 {slots: Array(3), apiHit: true}
71 ---ROTATE---
75 {ringElement: div.ring, prev: 288}
83 Prev is 288
87 <div class=​"ring" style=​"transform:​ rotateX(2088deg)​;​">​…​</div>​
90 move: 288
92 The diff is 0
96 rotateX(1728deg) for ring0
75 {ringElement: div.ring, prev: 72}
83 Prev is 72
87 <div class=​"ring" style=​"transform:​ rotateX(1224deg)​;​">​…​</div>​
90 move: 72
92 The diff is 0
96 rotateX(1152deg) for ring1
75 {ringElement: div.ring, prev: 144}
83 Prev is 144
87 <div class=​"ring" style=​"transform:​ rotateX(2088deg)​;​">​…​</div>​
90 move: 144
92 The diff is 0
96 rotateX(1224deg) for ring2

最佳答案

我认为问题是由于您每次渲染应用程序时都创建了 Pusher。我想将该代码移到应用程序之外可以解决问题。更新:并在应用程序准备就绪后注册事件

const pusher = new Pusher('XXXXXXX', {
cluster: 'XXX',
encrypted: true
});
const App = () => {
const [ slots, setSlots ] = useState([]);
const [ apiHit, setApiHit ] = useState(false);
useEffect(() => {
const channel = pusher.subscribe('my-channel');
const handler = data => {
console.log(`Got data from pusher ${data}`);
setSlots(data);
setApiHit(true);
};
channel.bind('my-event', handler);

return () => {
channel.unbind(null, handler);
channel.unsubscribe();
}
} ,[]);
return(
<div>
<SlotMachine slots={slots} apiHit={apiHit}/>
</div>
);
};

关于javascript - React props 的变化超出预期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58825617/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com