在地图函数中反应设置有状态变量

React setting Stateful variables in map function

我正在尝试设置一个显示按钮列表的 React 应用程序,用户可以按下一个按钮并转到包含有关国家/地区信息的页面。我正在使用 .map 函数以编程方式创建按钮。我正在使用 SQL 数据库来存储国家名称和有关国家的信息,然后调用 flask 路由将数据拉入我的 React 应用程序。为此,我使用了 async 函数。

这是我希望发生的过程: 我在 App.js 主路由器组件中设置了一些状态变量。然后,我使用按钮和 .map 函数将我的 setState 函数作为道具传递给我的组件。对于每个按钮,都可以选择在 App.js 组件中设置变量的状态。然后我会将 App.js 中的变量设置为与单击的按钮关联的值。从那里,我可以将这些有状态变量传递到我的国家/地区页面组件以进行显示。

实际发生了什么: 我将 props 传递给我的国家组件,希望国家和国家详细信息也随之传递,但我最终得到 undefined。看起来 undefined 可能是数据集的最后一个元素,因为我之前得到的结果是 Zimbabwe。这是我的 App.js 路由器代码:

export default function App() {

const [cname, setCName] = useState('')
const [pdf, setPdf] = useState('')
const [details, setDetails] = useState('')

  return (
    <div className="App">
      <BrowserRouter>
        {/* <Route exact path="/" component = { Home }/> */}
        <Route path="/cia" component = {(props) => <CIALanding {...props} setCName={setCName} setPdf={setPdf} setDetails={setDetails}/>}/>
        <Route path="/country" component={(props) => <Country {...props} setCName={setCName} details={details} cname={cname}/>}/>
        <Route path="/countrypage" component={CountryPage}/>          
      </BrowserRouter>
    </div>
  );
}

这是我的着陆页代码(使用 .map 函数)

export default function CIALanding(props) {


    const [countriesList, setCountriesList] = useState([])

    const getCountries = async () => {
        const response = await fetch('http://127.0.0.1:5000/countries');
        const data = await response.json();
        setCountriesList(data['country_list'].map((country) => {return (
            <Link to={{pathname:'/country',
            }}>
            <Country cname1={country[0]} details={country[2]} setCName={props.setCName}>{country[0]}</Country>
            </Link>
        )}))
    }

    useEffect(() => {
        getCountries()
    },[])
        return (
            <div>
            {countriesList}
            </div>
        )

}

这是我的国家组件代码

export default function Country(props) {

    return (
        <div>
         {console.log(props.cname)}
        <Button onClick={props.setCName(props.cname1)}>{props.cname1}</Button>
        </div>
    )

}

非常感谢您的帮助!

我不会完全回答你的问题,但我建议进行一些重构,也许这会解决你的问题。

首先,我会将获取代码移至 App 组件,这将允许组件更轻松地访问此数据(我添加了一些对获取状态更改的良好处理)。只有在成功获取数据后,您才会在此处呈现正确的路由。

const App = () => {
  const [status, setStatus] = useState(null);
  const [countries, setCountries] = useState([]);

  const getCountries = async () => {
    setStatus('loading');

    try {
      const response = await fetch('http://127.0.0.1:5000/countries');
      const data = await response.json();

      setCountriesList([...data['country_list']]);
      setStatus('success')
    } catch (error) {
      setSatus('error');
    }
  }

  useEffect(() => {
    getCountries();
  }, [])

  if (!status || status === 'error') {
    return <span>Loading data error</span>
  }

  if (status === 'loading') {
    return <span>Loading...</span>
  }

  return (
    <div className="App">
      <BrowserRouter>
        <Route path="/cia" component={(props) => <CIALanding {...props} countries={countries} />
        <Route path="/country/:countryId" component={(props) => <Country {...props} countries={countries} />    
      </BrowserRouter>
    </div>
  );
 }

第二件事——要显示正确的国家/地区页面,您不需要将任何数据设置为状态,您唯一需要做的就是使用正确的路径设置路由 /country/:countryId 和 Links,其中 countryId可以是作为数字或代码的唯一国家标识符。通过这样的设置,组件中只需要数据是国家数组,加载哪个国家由路由决定

登陆组件会很好很简单(你绝对不应该让 React 组件保持状态,只有数据)

const CIALanding = ({countries}) => (
  <div>
    {
      countries.map(({countryName, countryId}) => (
        <Link to={`/country/${countryId}`}>{countryName}</Link>
      ))
    }
  </div>
)

所以现在我们有了具有正确链接的国家/地区列表。然后国家/地区页面将通过参数 countryId

知道要显示哪些数据
const Country = ({match, countries}) => {
  //match object is passed by Route to this component and inside we have params object with countryId
  const {countryId} = match.params;
  const country = countries.find(country => country.countryId === countryId);

  if (country) {
    return (
      <div>
        Show info about selected country
      </div>
    );
  }

  return (
    <div>
      Sorry, cannot find country with id {countryId}
    </div>
  )
}

您可以通过单击 Link 并在浏览器中输入路径例如 .../country/ENG 来访问正确的国家/地区页面(我不知道您的数据结构,所以请记住使用正确的数据国家 ID) ;) 很抱歉,如果这不能解决您的问题,但我希望它至少包含一些重构的好主意 ;)