Reactjs 如何使用react钩子从一个同级组件到另一个同级组件提取道具和状态?

Reactjs 如何使用react钩子从一个同级组件到另一个同级组件提取道具和状态?,reactjs,react-hooks,Reactjs,React Hooks,我试图找出如何解决将道具和状态从一个组件传递到另一个组件的问题 父组件呈现如下 const Countdown = () => { return ( <div> <Timer taskNumber={1} /> <ClickScore taskNumber={1} numberOfAnswers={3} /> <FailScreen taskNumber={1}/> </div&

我试图找出如何解决将道具和状态从一个组件传递到另一个组件的问题

父组件呈现如下

 const Countdown = () => {
  return (
    <div>
      <Timer taskNumber={1} />
      <ClickScore taskNumber={1} numberOfAnswers={3} />
      <FailScreen taskNumber={1}/>
    </div>
  );
};
const倒计时=()=>{
返回(
);
};
计时器组件如下所示:

  const Timer = () => {
  const [timer, setTimer] = useState(10);
  const history = useHistory();

  useEffect(() => {
    let interval = setInterval(() => {
      if (timer > 0) {
        setTimer((timer) => timer - 1);
      } else {
        clearInterval(interval);
        if (score < numberOfAnswers) {
          history.push("/timesup");
        }
        history.push(`/tasks/${taskNumber}/page/3`);
      }
    }, 1000);
    return () => clearInterval(interval);
  }, [timer, history]);

  return <div className="countdown">{timer}</div>;
};
  const ClickScore = ({ taskNumber, numberOfAnswers }) => {
  const [score, setScore] = useState(0);

  const onGridClick = (row, col) => {
    if (taskNumber === 1) {
      if (
        (row === 1 && col === 2) ||
        (row === 2 && col === 1) ||
        (row === 2 && col === 3)
      ) {
        setScore((prevScore) => prevScore + 1);
      }
      return `${score}/${numberOfAnswers}`;
    }
   };

  const GridCell = ({ style, onGridClick }) => {
    const [clicked, setClicked] = useState(false);
    const handleClick = () => {
      if (!clicked) {
        setClicked(true);
        onGridClick();
      }
    };
    return (
      <div
        style={{...style}}
        onClick={handleClick}
        disable={clicked}></div>
    );
  };
  return (
    <>
      <div>
        <p id="score">{`${score}/${numberOfAnswers}`}</p>
      </div>
      <GridCell
        onGridClick={() => onGridClick(1, 1)}
        style={{
          left: 3,
          height: 170.48,
          width: 290.86,
          top: 37.91,
        }}
      />
    </>
  );
};
const Timer=()=>{
const[timer,setTimer]=useState(10);
const history=useHistory();
useffect(()=>{
let interval=setInterval(()=>{
如果(计时器>0){
设置计时器((计时器)=>计时器-1);
}否则{
间隔时间;
如果(分数clearInterval(interval);
},[计时器,历史];
返回{timer};
};
单击得分组件,如下所示:

  const Timer = () => {
  const [timer, setTimer] = useState(10);
  const history = useHistory();

  useEffect(() => {
    let interval = setInterval(() => {
      if (timer > 0) {
        setTimer((timer) => timer - 1);
      } else {
        clearInterval(interval);
        if (score < numberOfAnswers) {
          history.push("/timesup");
        }
        history.push(`/tasks/${taskNumber}/page/3`);
      }
    }, 1000);
    return () => clearInterval(interval);
  }, [timer, history]);

  return <div className="countdown">{timer}</div>;
};
  const ClickScore = ({ taskNumber, numberOfAnswers }) => {
  const [score, setScore] = useState(0);

  const onGridClick = (row, col) => {
    if (taskNumber === 1) {
      if (
        (row === 1 && col === 2) ||
        (row === 2 && col === 1) ||
        (row === 2 && col === 3)
      ) {
        setScore((prevScore) => prevScore + 1);
      }
      return `${score}/${numberOfAnswers}`;
    }
   };

  const GridCell = ({ style, onGridClick }) => {
    const [clicked, setClicked] = useState(false);
    const handleClick = () => {
      if (!clicked) {
        setClicked(true);
        onGridClick();
      }
    };
    return (
      <div
        style={{...style}}
        onClick={handleClick}
        disable={clicked}></div>
    );
  };
  return (
    <>
      <div>
        <p id="score">{`${score}/${numberOfAnswers}`}</p>
      </div>
      <GridCell
        onGridClick={() => onGridClick(1, 1)}
        style={{
          left: 3,
          height: 170.48,
          width: 290.86,
          top: 37.91,
        }}
      />
    </>
  );
};
const ClickScore=({taskNumber,numberOfAnswers})=>{
const[score,setScore]=useState(0);
const onGridClick=(行、列)=>{
如果(任务编号===1){
如果(
(行===1和列===2)||
(行===2和列===1)||
(行===2和列===3)
) {
setScore((prevScore)=>prevScore+1);
}
返回`${score}/${numberOfAnswers}`;
}
};
const GridCell=({style,onGridClick})=>{
const[clicked,setClicked]=useState(false);
常量handleClick=()=>{
如果(!单击){
setClicked(true);
onGridClick();
}
};
返回(
);
};
返回(

{`${score}/${numberOfAnswers}}

onGridClick(1,1)} 风格={{ 左:3,, 身高:170.48, 宽度:290.86, 排名:37.91, }} /> ); };
故障屏幕组件:

 const FailScreen = ({ prompt, taskNumber }) => {
  return (
    <div>
      <PromptBox
        title="Time's Up!"
        msg={`Oh no! You didn’t find all the ${prompt}`}
      />
      <Link to={`/tasks/${taskNumber}/page/1`}>
        <Button
          btn="tryAgainBtn
          name="TRY AGAIN"
        />
      </Link>
    </div>
 );
const FailScreen=({prompt,taskNumber})=>{
返回(

为了在组件之间传递道具,道具必须在其公共父级中可用。要将分数状态值作为共享上下文值,您可以执行以下操作:

const ScoreContext = useContext([]);

const ScoreProvider = (props) => {
    const [score, setScore] = useState(0); // Assuming your initial score is 0
    
    return (
        <ScoreContext.Provider value={[score, setScore]}>
            {props.children}
        </ScoreContext.Provider>
    );
};
const ScoreContext=useContext([]);
const ScoreProvider=(道具)=>{
const[score,setScore]=useState(0);//假设初始分数为0
返回(
{props.children}
);
};
然后在此上下文提供程序中包装子组件,如下所示:

const Countdown = () => {
    return (
        <ScoreProvider>
            <div>
                <Timer taskNumber={1} />
                <ClickScore taskNumber={1} numberOfAnswers={3} />
                <FailScreen taskNumber={1}/>
            </div>
        </ScoreProvider>
);
const倒计时=()=>{
返回(
);
})


ClickScore
组件中,这一行:
const[score,setScore]=useState(0);
应该变成
const[score,setScore]=useContext(ScoreContext);
以便使用和更新分数。在其余的每个组件中,您只需使用
const[score]=useContext访问分数值即可(ScoreContext);

不使用
上下文API
或状态管理工具,您只需创建一些
useState
变量,然后创建一些函数来更新这些变量,并将函数传递给
组件
。然后
组件
可以使用这些函数并传递所需的值,然后函数将运行并更新父组件中的状态t

它确实变得有点混乱,所以上下文API会更好,但下面是一个示例:

倒计时组件:

const Countdown = () => {
// create state for the click score
const [clickScore, setClickScore] = useState(0)

// create a function that will update the click store with given value
const updateClickScore = (score) => {
  setClickScore(score)
}
  return (
    <div>
      // Let's pass the updateClickScore function to Timer
      <Timer taskNumber={1} clickscore={updateClickScore} />

      // You can also pass the clickScore as a prop so other components can access it
      <ClickScore taskNumber={1} numberOfAnswers={3} score={clickScore} />

      // lets do it so the Failscreen can access it too, providing it needs to:
      <FailScreen taskNumber={1} score={clickScore} />

      // Now whenever the update is made, all components will receive the value

    </div>
  );
};
 const Timer = (clickscore) => {
   // your logic here

   // as an example lets pass the function to button click we will pass it the value 1 when clicked
   
// this will run the function in the Countdown component
    return <button onClick={() => clickscore(1)>Click Me</button>

   // Now once that has been clicked, all components will display 1 wherever the score prop is being rendered inside of them.
}

const倒计时=()=>{
//为单击分数创建状态
常量[clickScore,setClickScore]=使用状态(0)
//创建一个函数,该函数将使用给定值更新click store
const updateClickScore=(分数)=>{
设置ClickScore(分数)
}
返回(
//让我们将updateClickScore函数传递给Timer
//您还可以将clickScore作为道具传递,以便其他组件可以访问它
//让我们这样做,以便Failscreen也可以访问它,前提是它需要:
//现在,无论何时进行更新,所有组件都将收到该值
);
};
计时器组件:

const Countdown = () => {
// create state for the click score
const [clickScore, setClickScore] = useState(0)

// create a function that will update the click store with given value
const updateClickScore = (score) => {
  setClickScore(score)
}
  return (
    <div>
      // Let's pass the updateClickScore function to Timer
      <Timer taskNumber={1} clickscore={updateClickScore} />

      // You can also pass the clickScore as a prop so other components can access it
      <ClickScore taskNumber={1} numberOfAnswers={3} score={clickScore} />

      // lets do it so the Failscreen can access it too, providing it needs to:
      <FailScreen taskNumber={1} score={clickScore} />

      // Now whenever the update is made, all components will receive the value

    </div>
  );
};
 const Timer = (clickscore) => {
   // your logic here

   // as an example lets pass the function to button click we will pass it the value 1 when clicked
   
// this will run the function in the Countdown component
    return <button onClick={() => clickscore(1)>Click Me</button>

   // Now once that has been clicked, all components will display 1 wherever the score prop is being rendered inside of them.
}

const Timer=(点击分数)=>{
//你的逻辑在这里
//例如,让我们将函数传递给button click,我们将在单击时传递值1
//这将运行倒计时组件中的函数
返回clickscore(1)>单击我
//现在,单击该按钮后,所有组件都将显示1,无论其中的分数道具在何处渲染。
}
因此,您作为
道具
倒计时
计时器
传递的函数现在可以通过调用
clickscore(x)来使用
在计时器中。这将运行
倒计时组件中的功能
并传递您的号码,然后在
倒计时
中的状态下更新您的号码


然后,您可以将
倒计时中的
clickScore
状态作为道具传递给任何
组件
。这样,它们都将访问相同的号码,如果这是有意义的话?

IMHO,因为您打算在至少两个组件中使用
分数
任务号
答案号
更好的选择是通过使用上下文如何获得除这些道具之外的分数状态?这就是我遇到的问题。您首先必须使用分数值和分数设置器创建一个上下文。然后从该上下文中获取所需组件中的值。我将为您的示例代码生成一个答案tryThanks。因此,您只需设置ScoreProvider的值对于分数,我是否还需要添加taskNumber,numberOfAnswers,并将它们定义为'let taskNumber,numberOfAnswers;'?这要视情况而定。是否要在其他组件中更新它们的值??计时器和ClickScore需要全部3,FailScreen需要taskNumber