首先,在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
- 用户与某物进行交互(单击,按下,触摸,聚焦等)
- 您将新值设置为一个状态(或传递道具,以设置父级的状态...相同)
- 您呈现更改
- 在渲染生命周期/挂钩之后,您将产生副作用(例如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
不受其自身状态的完全控制。
如何执行此操作有几种选择,具体取决于您使用的状态管理策略。
- 如果仅在某些父组件中保持此状态:
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>
);
}
- 如果您使用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)
);
当前,您只是同时设置了选中状态。
,
让我仔细澄清一下。
第一个渲染。
- 名为Card的ischecked的道具由父组件NetworkArray给出。假设当时是 false 。
- 在子组件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