如何使用usestate在特定索引中拼接或推送新元素?

问题描述

我正在尝试在数组中插入新元素并更新基于数组的状态,但是更新状态后的问题是它未在组件中呈现。

  • 注意:我不太确定如何使用接头。 (我希望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>
  );
}

codesandbox

解决方法

您可以像这样使用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,将在您击中输入的元素之后返回元素(如果没有,则不返回任何内容)