如何在React中保留子组件的状态?

huangapple go评论72阅读模式
英文:

How to preserve the state of a child component in react?

问题

这是你的代码的翻译部分:

这里我创建了一个程序来接受不同的分数有一个增加按钮但问题是我想要增加 Rik 的分数 1 并点击下一个玩家 Sam 0如果我再次点击下一个玩家我希望看到 Rik 的分数 1但目前显示的是分数 0所以在父级渲染下如何保留子级的状态我可以使用本地存储或上下文来提供建议吗

import { useState } from 'react';

export default function Scoreboard() {
  const [isPlayerA, setIsPlayerA] = useState(true);
  return (
    <div>
      {/* {isPlayerA ? (
        <Counter person="Sam" />
      ) : (
        <Counter person="Rik" />
      )} */}
      {isPlayerA && (
        <Counter person="Sam" />
      )}
      { !isPlayerA &&(
        <Counter person="Rik" />
      )}
      <button onClick={() => {
        setIsPlayerA(!isPlayerA);
      }}>
        下一位玩家
      </button>
    </div>
  );
}

function Counter({ person }) {
  const [score, setScore] = useState(0);
  const [hover, setHover] = useState(false);

  let className = 'counter';
  if (hover) {
    className += ' hover';
  }

  return (
    <div
      className={className}
      onPointerEnter={() => setHover(true)}
      onPointerLeave={() => setHover(false)}
    >
      <h1>{person} 的分数: {score}</h1>
      <button onClick={() => setScore(score + 1)}>
        增加一分
      </button>
    </div>
  );
}

请注意,我已经将代码中的注释翻译为中文。

英文:

Here I had created a programme to take a different score, and one increment button is present, but the problem is that I want to increment Rik's score 1 and click the next player, Sam 0, and if I again click on the next player, I want to see Rik's score 1, but currently it's showing the score 0, so how to preserve the state of the child when parent rendering is given below. Can I use local storage or context to give any suggestions?

import { useState } from &#39;react&#39;;
export default function Scoreboard() {
const [isPlayerA, setIsPlayerA] = useState(true);
return (
&lt;div&gt;
{/* {isPlayerA ? (
&lt;Counter person=&quot;Sam&quot; /&gt;
) : (
&lt;Counter person=&quot;Rik&quot; /&gt;
)} */}
{isPlayerA &amp;&amp; (
&lt;Counter person=&quot;Sam&quot; /&gt;
) }
{ !isPlayerA &amp;&amp;(
&lt;Counter person=&quot;Rik&quot; /&gt;
)}
&lt;button onClick={() =&gt; {
setIsPlayerA(!isPlayerA);
}}&gt;
Next player
&lt;/button&gt;
&lt;/div&gt;
);
}
function Counter({ person }) {
const [score, setScore] = useState(0);
const [hover, setHover] = useState(false);
let className = &#39;counter&#39;;
if (hover) {
className += &#39; hover&#39;;
}
return (
&lt;div
className={className}
onPointerEnter={() =&gt; setHover(true)}
onPointerLeave={() =&gt; setHover(false)}
&gt;
&lt;h1&gt;{person}&#39;s score: {score}&lt;/h1&gt;
&lt;button onClick={() =&gt; setScore(score + 1)}&gt;
Add one
&lt;/button&gt;
&lt;/div&gt;
);
}

答案1

得分: 1

In any case, I think it is a good idea to store the score in the component <ScoreBoard/> Because based on your current code, the component <Counter/> will be re-rendered based on the value in isPlayerA. So the score is reset every time you change players.

我认为无论如何,将得分存储在组件 <ScoreBoard/> 中都是一个好主意。因为根据你当前的代码,组件 <Counter/> 将根据 isPlayerA 中的值重新渲染。所以每次更换玩家时都会重置得分。

英文:

In any case, I think it is a good idea to store the score in the component &lt;ScoreBoard/&gt; Because based on your current code, the component &lt;Counter/&gt; will be re-rendered based on the value in isPlayerA. So the score is reset every time you change players.

I have an alternative here, one drawback is that here I had to predefine the players in the score/setScore hook.

import { useState } from &#39;react&#39;

export default function Scoreboard() {
  const [isPlayerA, setIsPlayerA] = useState(true)
  const [score, setScore] = useState({
    Sam: 0,
    Rik: 0
  })

  return (
    &lt;div&gt;
      {/* {isPlayerA ? (
        &lt;Counter person=&quot;Sam&quot; /&gt;
      ) : (
        &lt;Counter person=&quot;Rik&quot; /&gt;
      )} */}
      {isPlayerA &amp;&amp; &lt;Counter person=&quot;Sam&quot; score={score} setScore={setScore} /&gt;}
      {!isPlayerA &amp;&amp; &lt;Counter person=&quot;Rik&quot; score={score} setScore={setScore} /&gt;}
      &lt;button
        onClick={() =&gt; {
          setIsPlayerA(!isPlayerA)
        }}
      &gt;
        Next player
      &lt;/button&gt;
    &lt;/div&gt;
  )
}

function Counter({ person, score, setScore }) {
  const [hover, setHover] = useState(false)

  let className = &#39;counter&#39;
  if (hover) {
    className += &#39; hover&#39;
  }

  return (
    &lt;div
      className={className}
      onPointerEnter={() =&gt; setHover(true)}
      onPointerLeave={() =&gt; setHover(false)}
    &gt;
      &lt;h1&gt;
        {person}&#39;s score: {score[person]}
      &lt;/h1&gt;
      &lt;button onClick={() =&gt; setScore({ ...score, [person]: (score[person] += 1) })}&gt;
        Add one
      &lt;/button&gt;
    &lt;/div&gt;
  )
}

答案2

得分: 1

使用本地存储或上下文是保留子组件 React 状态的一些方法。要实施这些技巧,请尝试以下步骤:

  1. 本地存储:使用它可以为您的数据存储需求提供很好的帮助。有了这个功能,您可以将有价值的文件和信息保存在用户的浏览器上,使事情更加高效。当用户想随时访问它而不必来回访问服务器时,它非常方便。因为它是 HTML5 标准的一部分,受到不同浏览器的支持,如 Safari、Chrome 和 Firefox。此外,它易于使用,并为程序存储重要数据提供额外的空间。使用本地存储,数据的持久性得到了保证,您可以轻松检索重要信息,减少麻烦。

使用本地存储是保存和访问浏览器中的玩家分数的巧妙方法。查看下面的修改后的代码,其中包含了这个功能。

每个玩家的分数将在此方法下记录并从本地存储中检索。这确保了即使重新呈现父组件,当前状态也会得到保留。

  1. 上下文在正确理解信息方面非常有用。它可以帮助我们解释某些短语或思想背后的含义,否则可能会模糊不清。通过上下文,我们可以更好地理解信息的传达,避免歧义。在解释某些内容时,考虑周围的情况或事件是至关重要的,以免误解。上下文在我们的理解中提供了更丰富的体验,是有效沟通和理解信息的重要因素。

要在更高级别管理状态并将其分发给子组件,一种替代方法是使用 React 上下文。以下是一个示例:

使用 useContext 钩子和 ScoreContext 提供程序,Counter 组件可以消耗分数状态,而无论如何更改都会得到保留。

英文:

Using local storage or context are some ways to preserve a child component's React state. To implement these techniques, try the following:

1)Local Storage: employing it can do wonders for your data storing needs. With this feature, you can save valuable files and information on the user's browser, which makes things more efficient. It comes in handy when users want to access it anytime without having to go back and forth to the server. Because it is a part of the HTML5 standard, it is supported by different browsers like Safari, Chrome, and Firefox. On top of that, it is easy to use and gives you extra space to store important data for your program. With local storage, data persistence is taken care of, and you can retrieve vital information without too much hassle.
Using local storage is a nifty way to save and access player scores from the browser. Check out the revised code below, which incorporates this feature.

import { useState, useEffect } from &#39;react&#39;;
export default function Scoreboard() {
const [isPlayerA, setIsPlayerA] = useState(true);
return (
&lt;div&gt;
{isPlayerA ? (
&lt;Counter person=&quot;Sam&quot; /&gt;
) : (
&lt;Counter person=&quot;Rik&quot; /&gt;
)}
&lt;button onClick={() =&gt; setIsPlayerA(!isPlayerA)}&gt;
Next player
&lt;/button&gt;
&lt;/div&gt;
);
}
function Counter({ person }) {
const [score, setScore] = useState(0);
const [hover, setHover] = useState(false);
let className = &#39;counter&#39;;
if (hover) {
className += &#39; hover&#39;;
}
useEffect(() =&gt; {
// Retrieve the score from local storage when the component mounts
const savedScore = localStorage.getItem(`${person}_score`);
if (savedScore) {
setScore(parseInt(savedScore, 10));
}
}, [person]);
useEffect(() =&gt; {
// Save the score to local storage whenever it changes
localStorage.setItem(`${person}_score`, score.toString());
}, [person, score]);
return (
&lt;div
className={className}
onPointerEnter={() =&gt; setHover(true)}
onPointerLeave={() =&gt; setHover(false)}
&gt;
&lt;h1&gt;{person}&#39;s score: {score}&lt;/h1&gt;
&lt;button onClick={() =&gt; setScore(score + 1)}&gt;
Add one
&lt;/button&gt;
&lt;/div&gt;
);
}

Each player's score will be recorded and retrieved from local storage under this approach. This guarantees that the current state will be preserved even if the parent component is re-rendered.

2)Context comes in handy when it comes to understanding information correctly. It can help us decipher the meaning behind certain phrases or ideas that may otherwise be obscure. With context, we can better understand the message that is being conveyed without ambiguity. It's essential to consider the surrounding circumstances or events when interpreting something, so as not to misinterpret it. Context provides a richer experience in our comprehension and is a vital element in communicating and understanding information effectively.
To manage state at a higher level and distribute it to child components, an alternative approach is to utilize React Context. An illustration is provided as follows:

import { useState, useContext, createContext } from &#39;react&#39;;
// Create a context to hold the score state
const ScoreContext = createContext();
export default function Scoreboard() {
const [isPlayerA, setIsPlayerA] = useState(true);
return (
&lt;ScoreContext.Provider&gt;
&lt;div&gt;
{isPlayerA ? (
&lt;Counter person=&quot;Sam&quot; /&gt;
) : (
&lt;Counter person=&quot;Rik&quot; /&gt;
)}
&lt;button onClick={() =&gt; setIsPlayerA(!isPlayerA)}&gt;
Next player
&lt;/button&gt;
&lt;/div&gt;
&lt;/ScoreContext.Provider&gt;
);
}
function Counter({ person }) {
const [score, setScore] = useContext(ScoreContext);
const [hover, setHover] = useState(false);
let className = &#39;counter&#39;;
if (hover) {
className += &#39; hover&#39;;
}
return (
&lt;div
className={className}
onPointerEnter={() =&gt; setHover(true)}
onPointerLeave={() =&gt; setHover(false)}
&gt;
&lt;h1&gt;{person}&#39;s score: {score}&lt;/h1&gt;
&lt;button onClick={() =&gt; setScore(score + 1)}&gt;
Add one
&lt;/button&gt;
&lt;/div&gt;
);
}

Using the useContext hook and ScoreContext provider, the Counter component consumes the score state that will be preserved regardless of changes.

huangapple
  • 本文由 发表于 2023年5月10日 14:05:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76215320.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定