Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/468.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么线条的顺序在这里很重要?_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript 为什么线条的顺序在这里很重要?

Javascript 为什么线条的顺序在这里很重要?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我正在创建一个,我不明白这两行如何在代码中排序: const timer = setTimeout(() => { if (picks.length === 2) { //this order that works setPicks([]) setCards(cards => cards.map((c) => ({ ...c, isFlipped: false }))); } }, 500) 在第一种情况下,

我正在创建一个,我不明白这两行如何在代码中排序:

const timer = setTimeout(() => {
   if (picks.length === 2) {
     //this order that works
     setPicks([])
     setCards(cards => cards.map((c) => ({ ...c, isFlipped: false })));            
   }
}, 500)

在第一种情况下,
matched
状态接收到正确的更新,因此为什么相似的卡匹配,但在第二种情况下,
matched
状态似乎没有得到正确的值

我不明白这两行的顺序是如何影响匹配状态的

const App = () => {
  const icons = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];

  const shuffle = cards => [...cards].sort(() => Math.random() - 0.5);

  const shuffledCards = useMemo(() => {
    return shuffle(icons).map((icon, i) => ({
      icon: icon,
      id: i,
      isFlipped: false
    }));
  });

  const [picks, setPicks] = useState([]);
  const [cards, setCards] = useState(shuffledCards);
  const [matched, setMatched] = useState([]);

  const handleClick = id => {
    !picks.includes(id) && picks.length !== 2 && setPicks([...picks, id]);
  };

  useEffect(() => {
    setCards(cards =>
      cards.map((c, i) =>
        picks.includes(c.id) ? { ...c, isFlipped: true } : c
      )
    );

    const matches = cards.reduce((matches, { icon, isFlipped }) => {
      !matches[icon] && (matches[icon] = 0);
      isFlipped && matches[icon]++;

      return matches;
    }, {});

    Object.entries(matches).forEach(([icon, count]) => {
      count === 2 && !matched.includes(icon) && setMatched([...matched, icon]);
    });

    const timer = setTimeout(() => {
      if (picks.length === 2) {
        //the problem is here, that order doesn't work
        setCards(cards => cards.map(c => ({ ...c, isFlipped: false })));
        setPicks([]);
      }
    }, 500);
    return () => clearTimeout(timer);
  }, [picks]);

  return (
    <div class="game">
      <Deck
        cards={cards}
        handleClick={handleClick}
        picks={picks}
        matched={matched}
      />
    </div>
  );
};

const Deck = ({ numbers, cards, ...props }) => {
  return (
    <div class="deck">
      {cards.map((c, i) => {
        return <Card i={i} card={c} {...props} />;
      })}
    </div>
  );
};

const Card = ({ handleClick, picks, card, i, matched }) => {
  const { icon, isFlipped, id } = card;

  return (
    <div
      className={`card${isFlipped ? " flipped" : ""} ${
        matched.includes(icon) ? "matched" : ""
      }`}
      onClick={() => handleClick(id)}
    >
      <div class="front" />
      <div class="back">{icon}</div>
    </div>
  );
};
const-App=()=>{
常量图标=['a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h'];
const shuffle=cards=>[…cards].sort(()=>Math.random()-0.5);
const shuffledCards=usemo(()=>{
返回洗牌(图标).map((图标,i)=>({
图标:图标,
id:我,
isFlipped:错误
}));
});
const[picks,setPicks]=useState([]);
const[cards,setCards]=使用状态(shuffledCards);
const[matched,setMatched]=useState([]);
const handleClick=id=>{
!picks.includes(id)&&picks.length!==2&&setPicks([…picks,id]);
};
useffect(()=>{
设置卡片(卡片=>
卡片.地图((c,i)=>
picks.includes(c.id){…c,isfliped:true}:c
)
);
const matches=cards.reduce((匹配,{icon,isfliped})=>{
!matches[icon]&(matches[icon]=0);
isFlipped&匹配[图标]+;
返回比赛;
}, {});
Object.entries(matches.forEach)([icon,count])=>{
计数===2&&!匹配。包括(图标)&&setMatched([…匹配,图标]);
});
常量计时器=设置超时(()=>{
if(picks.length==2){
//问题是,这个顺序不起作用
setCards(cards=>cards.map(c=>({…c,isfliped:false}));
集选([]);
}
}, 500);
return()=>clearTimeout(计时器);
},[picks]);
返回(
);
};
const Deck=({数字、卡片、…道具})=>{
返回(
{cards.map((c,i)=>{
返回;
})}
);
};
常量卡片=({handleClick,picks,Card,i,matched})=>{
const{icon,isfliped,id}=card;
返回(
handleClick(id)}
>
{icon}
);
};

每次拾取两张卡时,您询问的代码块负责重置卡状态

const timer = setTimeout(() => {
    if (picks.length === 2) {
    setCards(cards => cards.map(c => ({ ...c, isFlipped: false })));
    setPicks([]);
    }
}, 500);
在使用钩子设置卡片状态之前,必须通过钩子将空数组传递给已拾取卡片,从而重置已拾取卡片的状态,因为只有在未进行2次拾取时才能设置
拾取
。在当前逻辑中,需要将拾取长度重置为零,因为单击处理程序中有这样的内容

 const handleClick = id => {
    !picks.includes(id) && picks.length !== 2 && setPicks([...picks, id]);
  };

您询问的代码块负责在每次拾取两张卡时重置卡状态

const timer = setTimeout(() => {
    if (picks.length === 2) {
    setCards(cards => cards.map(c => ({ ...c, isFlipped: false })));
    setPicks([]);
    }
}, 500);
在使用钩子设置卡片状态之前,必须通过钩子将空数组传递给已拾取卡片,从而重置已拾取卡片的状态,因为只有在未进行2次拾取时才能设置
拾取
。在当前逻辑中,需要将拾取长度重置为零,因为单击处理程序中有这样的内容

 const handleClick = id => {
    !picks.includes(id) && picks.length !== 2 && setPicks([...picks, id]);
  };

问题:

这里的主要问题是代码中的以下行位置:

const matches = cards.reduce((matches, { icon, isFlipped }) => {
所以要理解这个问题,首先,我们需要理解上面的行位置有什么问题,请阅读评论以便更好地理解这个问题

setCards(cards => // <--------- 1.
    cards.map((c, i) =>  // <--------- 2.
        picks.includes(c.id) ? { ...c, isFlipped: true } : c
    )
);

// 1. current state of cards
// 2. returning updated state of cards

// so, if you are aware of async behavior or setState, then you know
// the below line will always point to snapshot of cards when the useEffect run
// and not to the 1. or 2.

// So here cards is pointing to snapshot when useEffect run 
const matches = cards.reduce((matches, { icon, isFlipped }) => {
工作演示

第二种解决方案(我建议采用这一种)

您可以为
cards
创建
useffect
值,以便始终获得更新的
cards
值,并基于此设置匹配值

  useEffect(() => {
    setCards(cards =>
      cards.map((c, i) =>
        picks.includes(c.id) ? { ...c, isFlipped: true } : c
      )
    );

    const timer = setTimeout(() => {
      if (picks.length === 2) {
        setCards(cards => cards.map(c => ({ ...c, isFlipped: false })));
        setPicks([]);
      }
    }, 500);
    return () => clearTimeout(timer);
  }, [picks]);

  useEffect(() => {
    const matches = cards.reduce((matches, { icon, isFlipped }) => {
      !matches[icon] && (matches[icon] = 0);
      isFlipped && matches[icon]++;

      return matches;
    }, {});

    Object.entries(matches).forEach(([icon, count]) => {
      count === 2 && !matched.includes(icon) && setMatched([...matched, icon]);
    });
  }, [cards]);
工作演示


问题:

这里的主要问题是代码中的以下行位置:

const matches = cards.reduce((matches, { icon, isFlipped }) => {
所以要理解这个问题,首先,我们需要理解上面的行位置有什么问题,请阅读评论以便更好地理解这个问题

setCards(cards => // <--------- 1.
    cards.map((c, i) =>  // <--------- 2.
        picks.includes(c.id) ? { ...c, isFlipped: true } : c
    )
);

// 1. current state of cards
// 2. returning updated state of cards

// so, if you are aware of async behavior or setState, then you know
// the below line will always point to snapshot of cards when the useEffect run
// and not to the 1. or 2.

// So here cards is pointing to snapshot when useEffect run 
const matches = cards.reduce((matches, { icon, isFlipped }) => {
工作演示

第二种解决方案(我建议采用这一种)

您可以为
cards
创建
useffect
值,以便始终获得更新的
cards
值,并基于此设置匹配值

  useEffect(() => {
    setCards(cards =>
      cards.map((c, i) =>
        picks.includes(c.id) ? { ...c, isFlipped: true } : c
      )
    );

    const timer = setTimeout(() => {
      if (picks.length === 2) {
        setCards(cards => cards.map(c => ({ ...c, isFlipped: false })));
        setPicks([]);
      }
    }, 500);
    return () => clearTimeout(timer);
  }, [picks]);

  useEffect(() => {
    const matches = cards.reduce((matches, { icon, isFlipped }) => {
      !matches[icon] && (matches[icon] = 0);
      isFlipped && matches[icon]++;

      return matches;
    }, {});

    Object.entries(matches).forEach(([icon, count]) => {
      count === 2 && !matched.includes(icon) && setMatched([...matched, icon]);
    });
  }, [cards]);
工作演示


我认为如果没有看到更多的代码(比如
setCards
setPicks
的实际功能,以及
匹配的
的定义/使用位置),我们无法提供帮助。链接是个问题@始终学习你的问题应该包括回答问题所需的一切。使用外部链接不是一个好主意,因为它可能会消失或改变,这就产生了限制未来使用的问题。这不是一个
async
/
useState
误解吗?不,我认为这不是问题,我知道在react中设置状态是不同步的,问题只是在app组件中的useffect,其他代码并不重要,谢谢,我认为如果没有看到更多的代码(比如
setCards
setPicks
的实际功能,以及
匹配的
的定义/使用位置),我们无法提供帮助。链接存在问题@始终学习你的问题应该包括回答问题所需的一切。使用外部链接不是一个好主意,因为它可能会消失或改变,这就产生了限制未来使用的问题。这不是一个
async
/
useState
误解吗?不,我认为这不是问题,我知道在react中设置状态是不同步的,问题只是在app组件中的useffect,其他代码并不重要,谢谢,两个片段都会在500毫秒后将拾取设置为空数组,在该持续时间内匹配的值应该是正确的,这让我很困惑!两个部件将在500毫秒后将拾取设置为空阵列