Reactjs React中的呈现和最佳实践

Reactjs React中的呈现和最佳实践,reactjs,react-hooks,Reactjs,React Hooks,我是React的初学者,我有一个关于渲染的问题,其中包括我使用UseFect渲染变量中的更改,该变量在useState中修饰 以下是声明: const CardRepo: React.FC<DadosCardRepo> = ({ Nome }) => { const [nomeRepo, setNomeRepo] = useState(Nome); const [data, setData] = useState({}); const [languages, setLangu

我是React的初学者,我有一个关于渲染的问题,其中包括我使用UseFect渲染变量中的更改,该变量在useState中修饰

以下是声明:

const CardRepo: React.FC<DadosCardRepo> = ({ Nome }) => {

const [nomeRepo, setNomeRepo] = useState(Nome);
const [data, setData] = useState({});
const [languages, setLanguages] = useState<Languages[]>([]);
useEffect(() => {
        getRepo(nomeRepo)
            .then(data => {
                setData(data);
            });
}, [nomeRepo]);

useEffect(() => {
        getLanguages(data['languages_url'])
            .then(data => {
                let total = 0;
                const languagesRef: Languages[] = [];
                Object.keys(data).map((key) => {
                    total += data[key];

                    languagesRef.push({ Nome: key, Porct: data[key] });
                });

                languagesRef.map((language, i, array) => {
                    setLanguages((oldValues) => [...oldValues, { Nome: language.Nome.toLowerCase(), Porct: +((language.Porct * 100) / total).toFixed(2) }]);
                });
            });
}, [data]);
{
  languages.map((el, i) => {
      return (
          <div className="progress-bar" id={el.Nome} key={i} style={{ width: el.Porct + '%' }}></div>
      );
  })
}
// calculate total value that gets memoized
const totalLangCount = useMemo(() => languages.reduce((total, val) => total + val.count , 0), [languages])

useEffect(() => {
  getLanguages(data['languages_url'])
      .then(data => {
          const languagesRef: Languages[] = [];
          Object.keys(data).forEach((key) => {
              // prepeare your languages properties
              const nome = key.toLowerCase();
              const count = data[key];

              languagesRef.push({ nome, count });
          });

          // avoid multiple setLanguages calls
          setLanguages(languagesRef)
      });
}, [data]);
{
  languages.map((el, i) => {
      return (
          //  here we are using array's index as key, but it's best to use some unique key overall instead
          <div className="progress-bar" id={el.nome} key={i} style={{ width: percentage(el.count, total) }}></div>
      );
  })
}
// utils percentage exported
export const percentage = (count, total) => ((count * 100) / total).toFixed(2) + '%'
其中,我在对nomeRepo进行更改时运行的第一个useEfect,在此方法中,我向getRepo服务发出请求

第二个,当我更改日期时,在这个方法中,我向getLanguages发出请求​​服务,并对响应进行处理以生成一个列表,我在其中分配语言

以下是列表:

const CardRepo: React.FC<DadosCardRepo> = ({ Nome }) => {

const [nomeRepo, setNomeRepo] = useState(Nome);
const [data, setData] = useState({});
const [languages, setLanguages] = useState<Languages[]>([]);
useEffect(() => {
        getRepo(nomeRepo)
            .then(data => {
                setData(data);
            });
}, [nomeRepo]);

useEffect(() => {
        getLanguages(data['languages_url'])
            .then(data => {
                let total = 0;
                const languagesRef: Languages[] = [];
                Object.keys(data).map((key) => {
                    total += data[key];

                    languagesRef.push({ Nome: key, Porct: data[key] });
                });

                languagesRef.map((language, i, array) => {
                    setLanguages((oldValues) => [...oldValues, { Nome: language.Nome.toLowerCase(), Porct: +((language.Porct * 100) / total).toFixed(2) }]);
                });
            });
}, [data]);
{
  languages.map((el, i) => {
      return (
          <div className="progress-bar" id={el.Nome} key={i} style={{ width: el.Porct + '%' }}></div>
      );
  })
}
// calculate total value that gets memoized
const totalLangCount = useMemo(() => languages.reduce((total, val) => total + val.count , 0), [languages])

useEffect(() => {
  getLanguages(data['languages_url'])
      .then(data => {
          const languagesRef: Languages[] = [];
          Object.keys(data).forEach((key) => {
              // prepeare your languages properties
              const nome = key.toLowerCase();
              const count = data[key];

              languagesRef.push({ nome, count });
          });

          // avoid multiple setLanguages calls
          setLanguages(languagesRef)
      });
}, [data]);
{
  languages.map((el, i) => {
      return (
          //  here we are using array's index as key, but it's best to use some unique key overall instead
          <div className="progress-bar" id={el.nome} key={i} style={{ width: percentage(el.count, total) }}></div>
      );
  })
}
// utils percentage exported
export const percentage = (count, total) => ((count * 100) / total).toFixed(2) + '%'
{
语言.map((el,i)=>{
返回(
);
})
}
我的问题与渲染有关,我知道如果我在变量“languages”中使用UseFect,我只能列出一些内容,我将在其中赋值​​随着变量的变化,我需要再次渲染,否则我就不能了

但是,当我对代码进行任何更改时,它只在更改的地方呈现,但它指定相同的值​​分配的,例如:[1,2,3]=>[1,2,3,1,2,3]。 我试着把它放进去​​([]),但它具有相同的行为
我想知道如何解决这个问题,如果这样打电话和列出列表是一种好的做法。

首先,有一种不好的做法是从道具创建派生状态
nomeRepo
来自props
Nome
,您应该尽可能避免这种派生状态。您最好删除
nomeRepo
状态并仅使用
Nome

您的第一次使用效果变为:

useEffect(() => {
        getRepo(Nome)
            .then(data => {
                setData(data);
            });
}, [Nome]);
第二个
useffect
在贴图内部触发了一个
setState
。这将多次触发setState,并创建多个重新渲染器。最好先准备语言数组,然后调用
setState
一次

此外,如果不使用返回的数组,并且只在每个元素上运行一些脚本,则应该使用
forEach
而不是
map

需要注意的一点是,您正在旧语言的基础上添加新语言。我假设语言应该与
数据['languages\u url']
值相关,这样您就不会将旧语言包含到setLanguages中

你可以考虑的是保持你的总价值而不是百分比。您可以将
total
存储到变量中,具体取决于
语言。并将百分比函数声明到
utils
文件夹中,并根据需要导入它

重构的第二个useEffect:

const CardRepo: React.FC<DadosCardRepo> = ({ Nome }) => {

const [nomeRepo, setNomeRepo] = useState(Nome);
const [data, setData] = useState({});
const [languages, setLanguages] = useState<Languages[]>([]);
useEffect(() => {
        getRepo(nomeRepo)
            .then(data => {
                setData(data);
            });
}, [nomeRepo]);

useEffect(() => {
        getLanguages(data['languages_url'])
            .then(data => {
                let total = 0;
                const languagesRef: Languages[] = [];
                Object.keys(data).map((key) => {
                    total += data[key];

                    languagesRef.push({ Nome: key, Porct: data[key] });
                });

                languagesRef.map((language, i, array) => {
                    setLanguages((oldValues) => [...oldValues, { Nome: language.Nome.toLowerCase(), Porct: +((language.Porct * 100) / total).toFixed(2) }]);
                });
            });
}, [data]);
{
  languages.map((el, i) => {
      return (
          <div className="progress-bar" id={el.Nome} key={i} style={{ width: el.Porct + '%' }}></div>
      );
  })
}
// calculate total value that gets memoized
const totalLangCount = useMemo(() => languages.reduce((total, val) => total + val.count , 0), [languages])

useEffect(() => {
  getLanguages(data['languages_url'])
      .then(data => {
          const languagesRef: Languages[] = [];
          Object.keys(data).forEach((key) => {
              // prepeare your languages properties
              const nome = key.toLowerCase();
              const count = data[key];

              languagesRef.push({ nome, count });
          });

          // avoid multiple setLanguages calls
          setLanguages(languagesRef)
      });
}, [data]);
{
  languages.map((el, i) => {
      return (
          //  here we are using array's index as key, but it's best to use some unique key overall instead
          <div className="progress-bar" id={el.nome} key={i} style={{ width: percentage(el.count, total) }}></div>
      );
  })
}
// utils percentage exported
export const percentage = (count, total) => ((count * 100) / total).toFixed(2) + '%'
呈现的语言:

const CardRepo: React.FC<DadosCardRepo> = ({ Nome }) => {

const [nomeRepo, setNomeRepo] = useState(Nome);
const [data, setData] = useState({});
const [languages, setLanguages] = useState<Languages[]>([]);
useEffect(() => {
        getRepo(nomeRepo)
            .then(data => {
                setData(data);
            });
}, [nomeRepo]);

useEffect(() => {
        getLanguages(data['languages_url'])
            .then(data => {
                let total = 0;
                const languagesRef: Languages[] = [];
                Object.keys(data).map((key) => {
                    total += data[key];

                    languagesRef.push({ Nome: key, Porct: data[key] });
                });

                languagesRef.map((language, i, array) => {
                    setLanguages((oldValues) => [...oldValues, { Nome: language.Nome.toLowerCase(), Porct: +((language.Porct * 100) / total).toFixed(2) }]);
                });
            });
}, [data]);
{
  languages.map((el, i) => {
      return (
          <div className="progress-bar" id={el.Nome} key={i} style={{ width: el.Porct + '%' }}></div>
      );
  })
}
// calculate total value that gets memoized
const totalLangCount = useMemo(() => languages.reduce((total, val) => total + val.count , 0), [languages])

useEffect(() => {
  getLanguages(data['languages_url'])
      .then(data => {
          const languagesRef: Languages[] = [];
          Object.keys(data).forEach((key) => {
              // prepeare your languages properties
              const nome = key.toLowerCase();
              const count = data[key];

              languagesRef.push({ nome, count });
          });

          // avoid multiple setLanguages calls
          setLanguages(languagesRef)
      });
}, [data]);
{
  languages.map((el, i) => {
      return (
          //  here we are using array's index as key, but it's best to use some unique key overall instead
          <div className="progress-bar" id={el.nome} key={i} style={{ width: percentage(el.count, total) }}></div>
      );
  })
}
// utils percentage exported
export const percentage = (count, total) => ((count * 100) / total).toFixed(2) + '%'

非常感谢您的回答和帮助,这对我帮助很大,我做了您所说的所有更改,一切都进行得很顺利,除了学习之外,欢迎您:)