在复选框上进行React Update Fetch点击

我有一个组件(卡),该组件具有使用Postgres在localhost数据库中跟踪的复选框。当我选中或取消选中该框时,条目将被放入networkusers表中。问题是,当我选中或取消选中该框,然后单击一个按钮以呈现其他组件,然后又将其与复选框一起返回到Card组件时,这些框未显示更新后的复选框。但是,如果我注销并重新登录,则所有框都将更新并与数据库同步。因此,如何更改以下组件中的复选框,如何使该组件呈现(或再次获取?)? TY。

import React,{ useState } from "react";

const onUpdateCB = (ischecked,loginuser,userid,setisChecked,handleCheck,event) => {

  console.log(ischecked,userid);

  fetch('http://localhost:3000/cb',{
      method: 'post',headers: {'Content-Type':'application/json'},body:JSON.stringify({
      loginuser,ischecked: ischecked
    })
  }).then(setisChecked(ischecked)); 
};

const Card = props => {
  const [isChecked,setisChecked] = useState(props.ischecked);
  return (
    <div
      classname="pointer bg-light-green dib br3 pa3 ma2 shadow-5"
      onClick={() => props.handleclick(props.id)}
      //onClick={(e) => e.stopPropagation()}

    >
      <div>
        <h3>{props.name}</h3>
        <p>{props.company}</p>
        <p>{props.phone}</p>
        <p>{props.email}</p>
        <p>{props.city}</p>
      </div>
      <div>
        My Network
        <input
          classname="largeCheckbox"
          type="checkbox"
          checked={isChecked}
          onClick={(event) =>
            onUpdateCB(!isChecked,props.loginuser.id,props.id,event.stopPropagation())
          }
        />
      </div>
    </div>
  );
};

export default Card;

网络阵列

import React from "react";
import Card from "./Card";

const NetworkArray = ({
  network,networkusers,handleChange,handleclick,loginuser
}) => {
  console.log("in network array",networkusers);

  const cardComponent = network.map((user,i) => {
    const ischecked = networkusers.filter(n => {
      var nw = n.id === loginuser.id && n.connections === network[i].id;
      return nw;
    });



    console.log("i'm checked",ischecked);

    return (

      <Card
        key={network[i].id}
        name={network[i].firstname + " " + network[i].lastname}
        company={network[i].company}
        phone={network[i].phone}
        email={network[i].email}
        city={network[i].city}
        ischecked={ischecked.length}
        handleChange={handleChange}
        handleclick={handleclick}
        id={network[i].id}
        loginuser={loginuser}
      />
    );
  });
  return <div>{cardComponent}</div>;
};

export default NetworkArray;
nanren41 回答:在复选框上进行React Update Fetch点击

首先,在React Application中必须遵循两个原则。

1。不要在任何应用程序状态下存储两个事实来源。 此刻,卡存储了自己的状态isChecked,并且Network上方的某个位置也已从数据库中获取值,并且isChecked也传递给了卡组件。

拥有多个真理来源不是很好,通常以后会再次困扰我们,因此规则1。不要拥有多个真理来源

Fix #1: remove "isChecked" state from Card.

import React,{ useState } from "react";

const onUpdateCB = (ischecked,loginuser,userid) => {

  console.log(ischecked,userid);

  fetch('http://localhost:3000/cb',{
    method: 'post',headers: {'Content-Type':'application/json'},body:JSON.stringify({
      loginuser,userid,ischecked: ischecked
    })
  }); 
};

const Card = props => {
  const { ischecked } = props;
  return (
    <div
      className="pointer bg-light-green dib br3 pa3 ma2 shadow-5"
      onClick={() => props.handleClick(props.id)}
      //onClick={(e) => e.stopPropagation()}
    >
      <div>
        <h3>{props.name}</h3>
        <p>{props.company}</p>
        <p>{props.phone}</p>
        <p>{props.email}</p>
        <p>{props.city}</p>
      </div>
      <div>
        My Network
        <input
          className="largeCheckbox"
          type="checkbox"
          checked={ischecked}
          onClick={(event) =>
            onUpdateCB(!isChecked,props.loginuser.id,props.id)
          }
        />
      </div>
    </div>
  );
};

export default Card;

....实际上,第一个主体应足以解决您的问题。但是以防万一你很好奇。

2。在渲染后进行副作用(componentDidMount,componentDidUpdate,useEffect)。

流程应该像这样, event => setState => render => side-effect

  1. 用户与某物进行交互(单击,按下,触摸,聚焦等)
  2. 您将新值设置为一个状态(或传递道具,以设置父级的状态...相同)
  3. 您呈现更改
  4. 在渲染生命周期/挂钩之后,您将产生副作用(例如api调用)

假设您的卡组件是独立的,不会从道具中获得价值。

const onUpdateCB = (ischecked,userid) => {
  return fetch('http://localhost:3000/cb',ischecked: ischecked
    })
  }); 
}

const Card = props => {
  const [data,setData] = useState({});

  // 2: set new state
  const onSelectCheckbox = (ischecked) => {
    const newData = { ...data,ischecked };
    setData(newData);
  }

  useEffect(() => {
    // 4. Watch if data.ischecked change,if yes perform side effect (call api)
    onUpdateCB(data.ischecked,props.id);
  },[data.ischecked]);

  // 3. re-render when data change.
  const { name,company,phone,email,city,ischecked } = data;
  return (
    <div className="pointer bg-light-green dib br3 pa3 ma2 shadow-5">
      <div>
        <h3>{name}</h3>
        <p>{company}</p>
        <p>{phone}</p>
        <p>{email}</p>
        <p>{city}</p>
      </div>
      <div>
        My Network
        <input
          className="largeCheckbox"
          type="checkbox"
          checked={ischecked}
          onClick={(event) =>
            onSelectCheckbox(!isChecked) // 1. User interact with checkbox
          }
        />
      </div>
    </div>
  );
};
,

我相信,问题出在Card的父母中。它会传递已检查状态(props.ischecked)的初始值,因此您可能需要将状态更改通知它,并使您的Card不受其自身状态的完全控制。

如何执行此操作有几种选择,具体取决于您使用的状态管理策略。

  1. 如果仅在某些父组件中保持此状态:
const Parent = () => {
  const [ ischecked,setChecked ] = useState(false);

  return (
    <Card ischecked={ ischecked } ... />
  );
}

在这种情况下,请提供回调以将状态更改为Card组件:

const Parent = () => {
  ...

  return (
    <Card ischecked={ ischecked } onCheckedChange={ setChecked } ... />
  );
}

...

const Card = (props) => {
  ...

    return (
    <div ...>
        ...
        <input
          ...
          checked={props.ischecked}
          onClick={(event) =>
            onUpdateCB(!isChecked,props.id,props.onCheckedChange,event.stopPropagation())
          }
        />
      </div>
    </div>
  );
}
  1. 如果您使用Redux来管理状态-将复选框状态移动到redux:
import { setChecked } from './actions';

const Card = props => {
  // the same as above
}

export default connect(state => ({
  ischecked: state.ischecked
}),{
  onCheckedChange: setChecked
})(Card);

P.S。此外,您的onUpdateCB()方法中有错别字-您应该使用函数作为Promise回调:

 }).then(
  () => setisChecked(ischecked)
); 

当前,您只是同时设置了选中状态。

,

让我仔细澄清一下。

第一个渲染。

  1. 名为Card的ischecked的道具由父组件NetworkArray给出。假设当时是 false
  2. 在子组件Card中,它初始化了一个名为isChecked的本地状态,该状态的初始值与prop ischecked(false)相同,并包装了一些逻辑以通过用户操作和API响应来更新状态。经过一系列用户操作,我们可以说最终将其更改为 true 。在代码中,仅更新了本地状态,但父项中的prop保持不变。

第二个渲染。 然后第二次渲染同一张Card时,再次 checked 的道具是假的,在Card中,由于计算的本地状态isChecked是false的,所以道具未被选中。

所以我们看到了Card之所以不显示更新的 isChecked 的原因,因为道具被选中未被更改。

解决此问题的方法是确保不仅对本地状态,而且对道具的检查已成功更新。我不确定如何在您的代码中使用此功能,因为被选中是由许多其他道具计算得出的,请自己尝试并祝您好运。

最后,为什么退出并登录后没有出现此问题?因为通过这种方式,父级中的道具已完全重新加载了包括被检查相关片段的更新数据。这样就得到了复选框的更新值。就是这样。

,

在React中,卸载组件时,它会释放其内部状态。

因此,当您回到它上面时,必须确保卡中的props.ischecked具有更新的值,该值来自于NetworkArray的network属性。

因此,当您回到该组件时,一旦完成network,就需要确保fetch道具是不同的。

通常,在NetworkArray上方,您将在ComponentDidMount中进行获取以更新网络道具。

这是整个代码的样子:

import React,{ useState } from "react";
import Card from "./Card";


class ComponentAboveNetworkArray extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
       /* ... */
       network: []
    }
  }

  componentDidMount() {
     fetch('http://localhost:3000/cb')
       .then(response => response.json())
       .then(json => this.setState({network: json.network}))
  }

  return (
    <NetworkArray /* ... */ network={this.state.network} />
  )
}


const NetworkArray = ({
  network,networkusers,handleChange,handleClick,loginuser
}) => {
  console.log("in network array",networkusers);

  const cardComponent = network.map((user,i) => {
      const ischecked = networkusers.some(n => {
         var nw = n.id === loginuser.id && n.connections === network[i].id;
         return nw;
      });

      console.log("i'm checked",ischecked);

      return (
         <Card
            key={network[i].id}
            name={network[i].firstname + " " + network[i].lastname}
            company={network[i].company}
            phone={network[i].phone}
            email={network[i].email}
            city={network[i].city}
            ischecked={ischecked}
            handleClick={handleClick}
            id={network[i].id}
            loginuser={loginuser}
         />
       );
     });
  return <div>{cardComponent}</div>;
};

export default NetworkArray;


本文链接:https://www.f2er.com/3010527.html

大家都在问