问题描述
我正在尝试在数组中插入新元素并更新基于数组的状态,但是更新状态后的问题是它未在组件中呈现。
- 注意:我不太确定如何使用接头。 (我希望
handleClick
函数在clicked元素下添加新元素,但似乎我也失败了。) - 注释2:我也尝试过
setstate((pre) => { pre.splice(index + 1,{ id: 3,text: "xxx",autoFocus: true }); return pre; });
,但效果不佳。
import React,{ useState } from "react";
import "./styles.css";
export default function App() {
let elements = [
{ id: 0,text: "first",autoFocus: true },{ id: 1,text: "second",{ id: 2,text: "third",autoFocus: true }
];
const [state,setstate] = useState(elements);
function handChange(e) {
if (e.keyCode == 13) {
const x = state;
const index = x.findindex((item) => item.id == e.target.id);
//i'm using autoFocus to move the focus (I-beam pointer) to the nex field.
//but i still get errors with it
// e.map((item) => Object.assign(item,{ autoFocus: false }));
x.splice(index + 1,autoFocus: true });
console.log(state); // you can see this update probarly
setstate(x); // but when I update state sometimes it don't render othertimes it take a while before render.
}
}
return (
<div className="App">
{state.map((e) => (
// when I say it don't render I mean the e value don't get updated.
<div
focus={e.focus}
contentEditable="true"
id={e.id}
onKeyUp={handChange}
>
{e.text}
</div>
))}
</div>
);
}
解决方法
您可以像这样使用splice
来更新阵列。
const newArray = [...state];
newArray.splice(e.target.id,newElement);
setstate(newArray);
由于splice
改变了原始数组。您可以使用散布运算符创建一个新数组,然后对其应用拼接。
这将创建一个带有状态的新数组。
[...state]
您可以检查接头here的文档
,代替使用
var options = {
root: null,rootMargin: '0px',threshold: [.5]
}
var startTime,leftTime,elapsedTime;
var capTimestamp,timeCap; // the timeout
var navedAwayAt;
var max,gonefor;
var callback = (entries,observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
startTime = entry.time; // in viewport when
entry.target.dataset.viewStartedAt = startTime; // capture in data attribute
if(entry.target.dataset.viewEndedAt) { entry.target.dataset.viewEndedAt = 'waiting'; }
if(entry.target.dataset.totalViewTime) { entry.target.dataset.totalViewTime = 'waiting'; }
window.addEventListener('beforeunload',handlePageUnload); // navigation
document.addEventListener("visibilitychange",handleVisibilityChange,false); // tab
capAndUnobserve(); // stop tracking after max time
trackCustomLink('ENTERED marquee'); // fire
console.log(entry.target); // log el
} else if (!entry.isIntersecting) {
max = 15000; //reset max if user tabbed away and then scrolled away
clearTimeout(timeCap); // stop the timeout on scroll away before time reached
window.removeEventListener("beforeunload",handlePageUnload); // no longer action nav
document.removeEventListener("visibilitychange",false); // no longer action tab away / minimise
leftTime = entry.time; // capture when they left
if (startTime) { // if they were ever there
elapsedTime = (parseInt(leftTime) - parseInt(startTime)); // duration
}
if (elapsedTime) {
customTracking('LEFT marquee');
customTracking('marquee SEEN FOR ' + elapsedTime/1000 + ' seconds');
entry.target.dataset.viewEndedAt = leftTime; // when they left in data attribute
target.dataset.totalViewTime = elapsedTime; // duration in data attribute
console.log(entry.target); // have a gander at the element attribs now
}
}
});
};
var observer = new IntersectionObserver(callback,options); // constructor
var target = document.querySelector('[id*=_xxxx_]'); // set target
observer.observe(target); // observe
var tabbedAwayAt;
var cameBackAt;
var gonefor;
var unloading = false;
var seg_1; var seg_2;
function handleVisibilityChange() {
if (!target.dataset.isOberving && !unloading) {
if (document.hidden) {
waseverhidden = true;
gonefor = 0;
max = 15000;
tabbedAwayAt = performance.now();
console.log('tabbedAwayAt ' + tabbedAwayAt);
seg_1 = tabbedAwayAt - startTime;
console.log('seenfor_1 ' + seg_1/1000);
} else {
cameBackAt = performance.now();
console.log('cameBackAt ' + cameBackAt);
gonefor = (cameBackAt - tabbedAwayAt);
console.log('gonefor ' + gonefor/1000);
console.log('original start time ' + startTime/1000);
startTime = startTime + gonefor;
max = 15000 + gonefor;
console.log('new max ' + max);
console.log('start time plus gone for ' + startTime/1000);
target.dataset.viewStartedAt = startTime;
}
return max
}
}
function capAndUnobserve() {
timeCap = setTimeout((max) => {
console.log(max);
clearTimeout(timeCap);
capTimestamp = performance.now();
alert('time cap happend at ' + capTimestamp);
customTracking('user has seen marquee for (at least) [max time] - !!end tracking!! ' + startTime + ' | ' + capTimestamp);
console.log(capTimestamp + ' ' + (capTimestamp - startTime)/1000); //should not be less than max e.g 15 seconds
observer.unobserve(target);
target.dataset.isOberving = 'false';
target.dataset.viewEndedAt = 'capTimestamp';
target.dataset.totalViewTime = capTimestamp - startTime;
},max ? max : 15000);
console.log('max ' + max);
};
function handlePageUnload(e) {
if (!target.dataset.isOberving) {
unloading = true;
navedAwayAt = performance.now();
console.log(e);
elapsedTime = (navedAwayAt - startTime)/1000;
console.log(navedAwayAt);
console.log("1: beforeunload,",document.hidden);
customTracking('Navigated away while in marquee,time spent in marquee was ' + elapsedTime + ' seconds');
clearTimeout(timeCap); // stop the timeout on scroll away before time reached
window.removeEventListener("beforeunload",handlePageUnload); // no longer action nav
document.removeEventListener("visibilitychange",false); // no longer action tab away / minimise
}
}```
我用这段代码替换
x.splice(index + 1,{ id: 3,text: "xxx",autoFocus: true });
setstate(x)
返回索引setstate((pre) => {
return [
...pre.slice(0,index + 1),autoFocus: true },...pre.slice(index + 1,state.length)
];
})
上的元素之前的元素+新元素+索引index + 1
上的元素之后的元素
- 例如,如果您有3个元素,然后在2d元素上按回车,则其索引为
index + 1
,您将在索引1
中及其后创建一个新元素,您将返回第三个元素,该元素位于1+1
之间的区域中,其中3是数组的长度。
替代解释:
-
1+1,3
会返回您击中的Enter之前的所有元素+您击中的Enter之前的所有元素。 -
...pre.slice(0,
这将在先前元素之后创建新元素 -
{ id: 3,
将在您击中输入的元素之后返回元素(如果没有,则不返回任何内容)