Child 组件 运行 仅在第一次渲染时出现,但不会 运行 在传递给相同 child 的每个状态更改时出现

Child Component runs only on first render but doesn't run on every state change that is passed on to that same child

我是 React 的初学者,遇到了一些问题。我有两个组成部分。一个是 parent(App.js),它将其状态传递给 child 组件(CardList)。另一个是 child ,它接收传递的状态并将其用作道具。我想做的是当我点击搜索按钮并提供一些用户名时,它将搜索相关用户名的数据,我将附加到 parent 功能组件和 child 中定义的状态数组,我将它作为道具发送,在 child 组件中,我将遍历 props.stateArray 的列表并打印相应的数据。即使我已经放置 console.log() 来检查流程是否转到此 child 组件,但此控制台仅在第一次渲染调用时运行,每次状态更改时控制台都不会运行记录任何 message.Please 找到下面的图像:-enter image description here




Parent Component **App.js**
import React, { useState } from 'react';
import Form from './Form';
import CardList from './CardList';

export default function App() {
  const [profiles, setProfiles] = useState([]);
  const addNewProfile=(profile)=>{
      profiles.push(profile);
      setProfiles(profiles);
  
     console.log(profiles);
  }
  return (
    <>
  
      <Form addProfile={addNewProfile}/>
      <CardList profilese={profiles}/>
    </>
  );
}


Child Component -- **CardList.js**
import React from 'react';
import Cardi from './Cardi';

export default function CardList(props)
{

   console.log("Everytime State of Parent change");
     return(
      <div>
        {props.profilese.map(profile => <Cardi key={profile.id} {...profile}/>)}
      </div>
       );
}


    Another Child Component -- **Form.js**
import React,{useState} from 'react';
import axios from 'axios';
import regeneratorRuntime from "regenerator-runtime";

export default function Form(props)
{
    const[username,setUsername]=useState("");

   const handleSubmit=async(event)=>{
         event.preventDefault();
         try{
        const resp= await axios.get
         (`https://api.github.com/users/${username}`);
         const data=await resp.data;
          props.addProfile(data);
         }catch(err)
         {
             console.log("Exception Occured"+ err);
         }
    }
    return(
     <form  onSubmit={handleSubmit}>
         <input type="text"
         value={username}
         onChange={event=>
            {setUsername(event.target.value)}}
     
         />
         <button >Search</button>
     </form>
    );
}


**Cardi.js**
import React from 'react';


export default function Cardi(props)
{

console.log(props.profile);
if(props.profile===undefined)
{
    return (
       <div>Can't find that username</div>
    );
}
else{
return (
  
  
    <>
       <img src={props.profile.avatar_url}/>
       <div className="info">
      <div className="name">{props.profile.name}</div>
      <div className="company">{props.profile.company}</div>
    </div>
    </>
  
);
}
}

enter image description here

为了在每次父级状态发生变化时重新渲染子级,您可以在子级中维护一个状态变量,并在每次 props 值发生变化时更新它(componentDidUpdate 可以工作)。现在不是直接输出道具...输出状态变量。

稍后将对此进行编辑以添加 demo/code。 希望这有帮助。

试试这个:

const addNewProfile=(profile)=>{
      setProfiles([...profiles, profile]);
}

你的状态是一个数组,是基于引用的。当您执行 profiles.push(profile) 时,您不会更改其引用。所以当你 setProfiles(profiles) 你传递的是相同的引用。 React 不会做深度匹配来比较。首先,避免直接改变状态。

更新

关于额外的问题:

1 - setState 是异步的,这意味着您的 console.log 不会打印已更新的状态,因为状态尚未更新。您可能希望在挂钩的 useEffect 中使用 console.log 语句,它会触发 Mount 和 Update 生命周期。或者你可以使用 react devtools.

2 - 你没有定义,因为你在 Cardi 访问错误的道具:

{props.profilese.map(profile => <Cardi key={profile.id} {...profile}/>)}

上面你传递的是配置文件属性而不是配置文件对象本身。但是在 cardi,您尝试访问配置文件对象,这不是您所拥有的。您可以将其更改为 profile = {profile},或者从 cardi 中删除所有配置文件链接并直接访问每个变量,如 props.name

App.js

 import React, { useState } from 'react';
import Form from './Form';
import CardList from './CardList';

export default function App() {
  const [profiles, setProfiles] = useState([]);
  const addNewProfile=(profile)=>{
    setProfiles([...profiles, profile]);
    console.log(profiles);
}
  return (
    <>

      <Form addProfile={addNewProfile}/>
      <CardList profilese={profiles}/>
    </>
  );
}

@buzatto 我已经更改了代码,但是当我第一次调用 api 时,它不会添加到配置文件数组中,当我第二次调用 api 时它会将 api 第一次命中的结果添加到配置文件状态数组。

第二个问题是我得到了从父组件 (CardList.js) 传递到子组件 (Cardi.js) 的配置文件属性的未定义值。

请参考以下截图:-

enter image description here

另一个问题:- 因为我在 CardList 中记录了配置文件道具的值,所以它提供了我在父组件中定义的状态的更新值(App.js),而状态本身在父组件中定义仍然没有得到更新。 请参考以下截图:- enter image description here