Reactjs 单击复选框时响应更新获取
我有一个组件(卡),它有一些复选框,这些复选框在本地主机数据库中使用Postgres进行跟踪。当我选中或取消选中该框时,一个条目会被放入networkusers表中。问题是,当我选中或取消选中复选框,然后单击按钮渲染不同的组件,然后返回带有复选框的卡片组件时,这些框不会显示更新的复选框。但是,如果我注销并重新登录,所有框都会更新并与数据库同步。那么,如何让组件在以下组件中的复选框更改后立即进行渲染(或再次获取?)?泰Reactjs 单击复选框时响应更新获取,reactjs,checkbox,react-hooks,fetch-api,Reactjs,Checkbox,React Hooks,Fetch Api,我有一个组件(卡),它有一些复选框,这些复选框在本地主机数据库中使用Postgres进行跟踪。当我选中或取消选中该框时,一个条目会被放入networkusers表中。问题是,当我选中或取消选中复选框,然后单击按钮渲染不同的组件,然后返回带有复选框的卡片组件时,这些框不会显示更新的复选框。但是,如果我注销并重新登录,所有框都会更新并与数据库同步。那么,如何让组件在以下组件中的复选框更改后立即进行渲染(或再次获取?)?泰 import React, { useState } from "react"
import React, { useState } from "react";
const onUpdateCB = (ischecked, loginuser, userid, setisChecked,handleCheck,event) => {
console.log(ischecked, loginuser, userid);
fetch('http://localhost:3000/cb', {
method: 'post',
headers: {'Content-Type':'application/json'},
body:JSON.stringify({
loginuser,
userid,
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, setisChecked,event.stopPropagation())
}
/>
</div>
</div>
);
};
export default Card;
import React,{useState}来自“React”;
const onUpdateCB=(已检查、登录用户、用户ID、已检查、handleCheck、事件)=>{
log(ischecked、logiuser、userid);
取('http://localhost:3000/cb', {
方法:“post”,
标题:{'Content-Type':'application/json'},
正文:JSON.stringify({
登录用户,
用户ID,
ischecked:ischecked
})
}).然后(设置检查(设置检查));
};
康斯特卡=道具=>{
const[isChecked,setisChecked]=useState(props.isChecked);
返回(
props.handleClick(props.id)}
//onClick={(e)=>e.stopPropagation()}
>
{props.name}
{props.company}
{props.phone}
{props.email}
{props.city}
我的网络
onUpdateCB(!isChecked,props.logiuser.id,props.id,setisChecked,event.stopPropagation())
}
/>
);
};
导出默认卡;
网络阵列
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;
从“React”导入React;
从“/Card”导入卡片;
常量网络数组=({
网络,,
网络用户,
handleChange,
handleClick,
登录用户
}) => {
console.log(“在网络阵列中”,networkusers);
const cardComponent=network.map((用户,i)=>{
const ischecked=networkusers.filter(n=>{
var nw=n.id==logiuser.id&&n.connections===network[i].id;
返回西北方向;
});
log(“我已检查”,已检查);
返回(
);
});
返回{cardComponent};
};
导出默认网络数组;
我相信,问题出在卡的家长身上。它传递检查状态的初始值(props.ischecked
),因此您可能需要通知它状态更改,并使您的卡在没有自身状态的情况下完全受控
根据您使用的状态管理策略,有几种方法可供选择
如果仅在某个父组件中保持此状态:
const Parent=()=>{
const[ischecked,setChecked]=使用状态(false);
返回(
);
}
在这种情况下,提供回调以将状态更改为卡
组件:
const Parent=()=>{
...
返回(
);
}
...
康斯特卡=(道具)=>{
...
返回(
...
onUpdateCB(!isChecked,props.logiuser.id,props.id,props.onCheckedChange,event.stopPropagation())
}
/>
);
}
如果使用Redux管理状态-将复选框状态移动到Redux:
从“/actions”导入{setChecked};
康斯特卡=道具=>{
//同上
}
导出默认连接(状态=>({
ischecked:state.ischecked
}), {
onCheckedChange:setChecked
})(卡);
另外,您的onUpdateCB()
方法中有一个输入错误-您应该使用一个函数作为承诺回调:
然后(
()=>setisChecked(ischecked)
);
目前,您只需同时设置选中状态。首先,在React应用程序中必须遵循两个原则
1。不要在任何应用程序状态下存储两个真实来源。
此时,卡存储其自己的状态isChecked
,并且网络上的某个位置
从数据库中获取值,并将isChecked
传递给卡组件
拥有多个真理来源是不好的,而且通常会在以后再来困扰我们,所以第一条规则,不要拥有多个真理来源
Fix#1:从卡中删除“isChecked”状态。
import React, { useState } from "react";
const onUpdateCB = (ischecked, loginuser, userid) => {
console.log(ischecked, loginuser, 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;
让我仔细澄清一下
第一次渲染
名为ischecked of Card的属性由父组件NetworkArray提供。让我们假设当时它是假的
在子组件卡中,它初始化了一个名为isChecked的本地状态,该状态的初始值与prop isChecked(false)相同,并封装了一些逻辑,以通过用户操作和API响应更新状态。在一系列用户操作之后,假设它最终被更改为true。在代码中,只有本地状态更新,但父级中的道具保持不变
第二次渲染。
然后第二次渲染同一张卡时,属性ischecked再次为false,在该卡中,由于计算的局部状态ischecked为false,因此未选中该属性
因此,我们看到了卡没有显示更新的isChecked的原因,因为道具isChecked没有更改
解决此问题的方法是确保对属性进行检查并成功更新,而不仅仅是本地状态。我不知道如何在您的代码中实现这一点,因为已检查是由许多其他道具计算出来的,请尝试自己实现,祝您好运
最后,为什么在注销和登录后没有出现此问题?因为通过这种方式,父级中的道具完全重新加载了更新的数据,包括ischecked相关片段。所以您得到了复选框的更新值。就是这样。在React中,当一个组件卸载时,它会释放其内部状态
因此,当您返回时,您必须确保从车上检查道具
const onUpdateCB = (ischecked, loginuser, userid) => {
return fetch('http://localhost:3000/cb', {
method: 'post',
headers: {'Content-Type':'application/json'},
body:JSON.stringify({
loginuser,
userid,
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.loginuser.id, 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>
);
};