首页 > 解决方案 > 过滤数据并将其返回到“永久”数据旁边 - 反应

问题描述

TextField从 MUI 库中添加了一个,并使用一个useRef钩子在用户键入内容时捕获值“live”。目的是仅过滤包含他键入的字符的费率。截至目前:

Object.keys(rates["rates"]) // ["EUR", "RON", "CZK", ...]

我添加了一个表单,我希望它保持不变,但按钮应该动态变化。如果用户没有输入任何我想返回的东西(就像没有被过滤)

我的尝试:

import React, {useEffect, useRef, useState} from 'react'
import Button from '@mui/material/Button';
import CircularProgress from '@mui/material/CircularProgress';
import Box from '@mui/material/Box';
import TextField from '@mui/material/TextField';

const RatesButton = () => {
    const rateRef = useRef('')
    const [rates, setRates] = useState([]);
    useEffect(
        () => {
            fetch("https://api.vatcomply.com/rates")
                .then(ratesResponse => ratesResponse.json())
                .then(rates => setRates(rates));
        }
        , [])


    if (rates.length === 0) {
        return (
            <Box sx={{display: 'flex', justifyContent: 'center'}}>
                <CircularProgress/>
            </Box>
        )
    }

    const rateSearch = () => {
        Object.keys(rates["rates"]).filter(
            rate => rate.includes(rateRef.current.value)
        ).map(rate => {

                return (
                    <Button>
                        {rate}
                    </Button>
                )
            }
        )

    }

    return (
        <>
            <br/>
            <TextField id="rate-search" onChange={rateSearch} inputRef={rateRef} label="Rate" variant="outlined"/>
        </>
    )
}


export default RatesButton

我认为它工作得很好,我可以访问用户输入的参考,过滤所有包含字母的比率,并将每个比率映射到 MUI Button。问题是它们没有以某种方式显示,我很迷茫,如何同时从两个不同的函数返回,同时保持一个持久性(输入字段),这很令人困惑

输入图片

不幸的是,按钮不显示...

标签: javascriptreactjsmaterial-ui

解决方案


您应该使用受控模式并将您TextField的值存储在使用useState而不是状态中,useRef因为更改 ref 值不会触发重新渲染,因此 UI 不会更新。您的代码中还有很多其他错误的地方,我已经全部修复了,如果您有任何不明白的地方,请随时问我:

const RatesButton = () => {
  const [value, setValue] = useState("");
  const [rates, setRates] = useState({});

  useEffect(() => {
    fetch("https://api.vatcomply.com/rates")
      .then((ratesResponse) => ratesResponse.json())
      .then((rates) => setRates(rates.rates ?? {}));
  }, []);

  return (
    <>
      {Object.keys(rates).length === 0 && (
        <Box sx={{ display: "flex", justifyContent: "center" }}>
          <CircularProgress />
        </Box>
      )}
      {Object.keys(rates)
        .filter((rate) => rate.toLowerCase().includes(value.toLowerCase()))
        .map((rate) => {
          return <Button>{rate}</Button>;
        })}
      <br />
      <TextField
        id="rate-search"
        onChange={(e) => setValue(e.target.value)}
        // inputRef={value}
        label="Rate"
        variant="outlined"
      />
    </>
  );
};

现场演示

Codesandbox 演示


推荐阅读