从另一个功能组件访问功能组件状态

Accessing a functional component state from another functional component


我正在编写的程序根据用户的生日告诉用户他们的星座(来自 select 元素的用户输入)。我使用路由器在三个页面之间切换:主页、测验和结果。这三个组件存储在 src 中的 Pages 文件夹中。 **测验包含 CalcSign,计算人的符号的组件。 signState 是测验组件中的一种状态。我想在结果页面上显示 signState** 并可能在结果中的未来比较语句中使用它。目前,signState 不显示在结果页面上。
谢谢

Quiz.js

import React from 'react';
import {useState} from 'react';
import {useNavigate} from "react-router-dom";

function Quiz () {
  const [monthState, setMonth] = useState("");
  const [dayState, setDay] = useState("");
  const [signState, setSign] = useState("");
let navigate = useNavigate();

function CalcSign() 
{
  if((monthState == 'mar' && dayState > 20)|| (monthState == 'apr' && dayState <= 19))
  {
    setSign("Aries");
    return (<> </>);
  }
  else if((monthState == 'apr' && dayState > 19)|| (monthState == 'may' && dayState <= 20))
  {
    setSign("Taurus");
    return (<> </>);
  }
  else if((monthState == 'may' && dayState > 20)|| (monthState == 'jun' && dayState <= 20))
  {
    setSign("Gemini");
    return (<> </>);
  }
  else if((monthState == 'jun' && dayState > 20)|| (monthState == 'jul' && dayState <= 22))
  {
    setSign("Cancer");
    return (<> </>);
  }
  else if((monthState == 'jul' && dayState > 22)|| (monthState == 'aug' && dayState <= 22))
  {
    setSign("Leo");
    return (<> </>);
  }
  else if((monthState == 'aug' && dayState > 22)|| (monthState == 'sep' && dayState <= 22))
  {
    setSign("Virgo");
    return (<> </>);
  }
  else if((monthState == 'sep' && dayState > 22)|| (monthState == 'oct' && dayState <= 22))
  {
    setSign("Libra");
    return (<> </>);
  }
  else if((monthState == 'oct' && dayState > 22)|| (monthState == 'nov' && dayState <= 21))
  {
    setSign("Scorpio");
    return (<> </>);
  }
  else if((monthState == 'nov' && dayState > 21)|| (monthState == 'dec' && dayState <= 21))
  {
    setSign("Sagitarius");
    return (<> </>);
  }
  else if((monthState == 'dec' && dayState > 21) || (monthState == 'jan' && dayState <= 19))
    {
      setSign("capricorn");
      return (<> </>);
    
    }
  else if((monthState == 'jan' && dayState > 19)|| (monthState == 'feb' && dayState <= 18))
  {
    setSign("Aquarius");
    return (<> </>);
  }
  else if((monthState == 'feb' && dayState > 18)|| (monthState == 'mar' && dayState <= 20))
  {
    setSign("Pisces");
    return (<> </>);
  }

    else
    {setSign("not");
       return (<p>You didn't enter your birthday correctly</p>);}  
  }
  
return (
    <div>
    <label for="quiz">Please select your birthday</label>
<select name="month" id="month" onChange = {(e) => 
  {const selectedMonth = e.target.value;
   setMonth(selectedMonth);}}>  

  <option value="defaultMonth">Birth month</option>
  <option value="jan">January</option>
  <option value="feb">February</option>
  <option value="mar">March</option>
  <option value="apr">April</option>
  <option value="may">May</option>
  <option value="jun">June</option>
  <option value="jul">July</option>
  <option value="aug">August</option>
  <option value="sep">September</option>
  <option value="oct">October</option>
  <option value="nov">November</option>
  <option value="dec">December</option>
</select>

<select name="day" id="day" onChange = {(e) => 
  {const selectedDay = e.target.value;
   setDay(selectedDay);}}>

  <option value="defaultDay">select a day</option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
  <option value="6">6</option>
  <option value="7">7</option>
  <option value="8">8</option>
  <option value="9">9</option>
  <option value="10">10</option>
  <option value="11">11</option>
  <option value="12">12</option>
  <option value="13">13</option>
  <option value="14">14</option>
  <option value="15">15</option>
  <option value="16">16</option>
  <option value="17">17</option>
  <option value="18">18</option>
  <option value="19">19</option>
  <option value="20">20</option>
  <option value="21">21</option>
  <option value="22">22</option>
  <option value="23">23</option>
  <option value="24">24</option>
  <option value="25">25</option>
  <option value="26">26</option>
  <option value="27">27</option>
  <option value="28">28</option>
  <option value="29">29</option>
  <option value="30">30</option>
  <option value="31">31</option>
</select>

<CalcSign/> 
        <button type = "button" onClick = {() => {navigate("/result");}} >What's my sign</button>
        {dayState} //show that the assignment works properly
        {signState} //show that the assignment works properly
    </div>
  );
}
export default Quiz; 

Result.js

import React from 'react';
import Quiz from "./Quiz";

function Result() {
 const displaySign = (props) => {
    return (<p>{props.signState} </p>)
  } 
 

return (
    <div>
        <h2>Your result is </h2> 
        <div> {displaySign(<Quiz/>)}</div>
      
    </div>
  );
}
export default Result; 

我也在<h2> Your result is </h2>

下尝试了<p> {signState} </p><p><Quiz signState/> </p>

您需要在 navigate('/result') 调用中传递一个状态对象。换句话说,将该行更改为 onClick = {() => navigate('/result', { signState })}。在您的结果组件中,如果不是直接路由,您可能需要调用useLocation挂钩来读取状态。

import React from 'react';
import Quiz from "./Quiz";

function Result() {
 const location = useLocation();
 const { signState } = location.state;
 

return (
    <div>
        <h2>Your result is </h2> 
        <div>{signState}</div>
    </div>
  );
};

export default Result; 

为了简单地解决您需要通过路由转换将一些值传递到 "/result" 页面,请在路由状态中传递 signState 状态。

useNavigate

这是 useNavigatenavigate 函数类型定义。

declare function useNavigate(): NavigateFunction;

interface NavigateFunction {
  (
    to: To,
    options?: { replace?: boolean; state?: any }
  ): void;
  (delta: number): void;
}

调用 navigate 发出命令式导航时,使用第二个参数 options 发送路由状态。

<button
  type="button"
  onClick={() => {
    navigate(
      "/result",                // <-- `to` arg
      { state: { signState } }, // <-- `options` arg
    );
  }}
>
  What's my sign
</button>

通过 location 对象访问接收组件上的路由状态。

useLocation

declare function useLocation(): Location;

interface Location<S extends State = object | null>
  extends Path {
  state: S;
  key: Key;
}
import { useLocation } from 'react-router-dom';

function Result() {
  const { state } = useLocation();

  return (
    <div>
      <h2>Your result is </h2> 
      <div>
        <p>{state.signState}</p>
      </div>
    </div>
  );
}