Reactjs React Hooks-与多个动态组件共享父状态
我目前正在构建一个带有挂钩的React应用程序。 我有一个组件(视图),它从某处加载数据并动态生成组件(Clicker、ClickerDisplay),一方面显示数据,另一方面交替显示数据 这个应用程序基本上可以运行,但我关心的是它的性能。我的状态每100毫秒更新一次,如果所有内容都在更改后重新提交,这将是一个巨大的开销 是否可以只重新启动应该更改的组件 另一件对我来说很难看的事情是我更新状态的方式<代码>设置状态([…状态])代码>有没有更好的方法 旁注: 在我的示例代码id中,我目前只将项属性传递到子组件中,但我计划将整个项传递到子组件中 我还想保留父组件中的主要状态,因为应用程序的状态应该被建立并保存到一个大的JSON对象中 数据Reactjs React Hooks-与多个动态组件共享父状态,reactjs,Reactjs,我目前正在构建一个带有挂钩的React应用程序。 我有一个组件(视图),它从某处加载数据并动态生成组件(Clicker、ClickerDisplay),一方面显示数据,另一方面交替显示数据 这个应用程序基本上可以运行,但我关心的是它的性能。我的状态每100毫秒更新一次,如果所有内容都在更改后重新提交,这将是一个巨大的开销 是否可以只重新启动应该更改的组件 另一件对我来说很难看的事情是我更新状态的方式设置状态([…状态])有没有更好的方法 旁注: 在我的示例代码id中,我目前只将项属性传递到子组件
//Some Random Data
const things = [
{
"id": 0,
"name": "thing 1",
},
{
"id": 1,
"name": "thing 2",
},
{
"id": 2,
"name": "thing 3",
}
];
View.js
export default function View(props) {
const tmp = things.map(item => {
return { ...item, amount: 0 };
});
const [state, setState] = useState(tmp);
//alternates the amount and updates the state
function updateAmount(item, newAmount) {
item.amount = newAmount;
setState([...state]);
}
function createClicker(item) {
const { name, amount } = item;
return (<Clicker
name={name}
amount={amount}
clicked={() => updateAmount(item, amount + 1)} />
);
}
function createClickerDisplay(item) {
const { name, amount } = item;
return (<ClickerDisplay
name={name}
amount={amount} />
);
}
return (
<ul>
{state.map(item =>
<li>
{createClicker(item)} = {createClickerDisplay(item)}
</li>
)}
</ul>
);
}
//component to alternate data
function Clicker(props) {
const { clicked, name, amount } = props;
return <button onClick={() => clicked(name)}>{name}: {amount}</button>;
}
//component to display data
function ClickerDisplay(props) {
const { name, amount } = props;
return <span>{name}: {amount}</span>;
}
导出默认功能视图(道具){
const tmp=things.map(item=>{
返回{…项,金额:0};
});
常量[状态,设置状态]=使用状态(tmp);
//更改金额并更新状态
函数updateAmount(项,newAmount){
item.amount=新金额;
设置状态([…状态]);
}
函数createClicker(项目){
常量{name,amount}=项目;
返回(updateAmount(项目,金额+1)}/>
);
}
函数createClickerDisplay(项){
常量{name,amount}=项目;
返回(
);
}
返回(
{state.map(项=>
-
{createClicker(项目)}={createClickerDisplay(项目)}
)}
);
}
Clicker.js
export default function View(props) {
const tmp = things.map(item => {
return { ...item, amount: 0 };
});
const [state, setState] = useState(tmp);
//alternates the amount and updates the state
function updateAmount(item, newAmount) {
item.amount = newAmount;
setState([...state]);
}
function createClicker(item) {
const { name, amount } = item;
return (<Clicker
name={name}
amount={amount}
clicked={() => updateAmount(item, amount + 1)} />
);
}
function createClickerDisplay(item) {
const { name, amount } = item;
return (<ClickerDisplay
name={name}
amount={amount} />
);
}
return (
<ul>
{state.map(item =>
<li>
{createClicker(item)} = {createClickerDisplay(item)}
</li>
)}
</ul>
);
}
//component to alternate data
function Clicker(props) {
const { clicked, name, amount } = props;
return <button onClick={() => clicked(name)}>{name}: {amount}</button>;
}
//component to display data
function ClickerDisplay(props) {
const { name, amount } = props;
return <span>{name}: {amount}</span>;
}
//组件到备用数据
功能点击器(道具){
const{clicked,name,amount}=props;
返回单击的(名称)}>{name}:{amount};
}
单击display.js
export default function View(props) {
const tmp = things.map(item => {
return { ...item, amount: 0 };
});
const [state, setState] = useState(tmp);
//alternates the amount and updates the state
function updateAmount(item, newAmount) {
item.amount = newAmount;
setState([...state]);
}
function createClicker(item) {
const { name, amount } = item;
return (<Clicker
name={name}
amount={amount}
clicked={() => updateAmount(item, amount + 1)} />
);
}
function createClickerDisplay(item) {
const { name, amount } = item;
return (<ClickerDisplay
name={name}
amount={amount} />
);
}
return (
<ul>
{state.map(item =>
<li>
{createClicker(item)} = {createClickerDisplay(item)}
</li>
)}
</ul>
);
}
//component to alternate data
function Clicker(props) {
const { clicked, name, amount } = props;
return <button onClick={() => clicked(name)}>{name}: {amount}</button>;
}
//component to display data
function ClickerDisplay(props) {
const { name, amount } = props;
return <span>{name}: {amount}</span>;
}
//用于显示数据的组件
功能点击显示(道具){
常量{name,amount}=props;
返回{name}:{amount};
}
除非配置为根据状态和道具的特定更改有条件地重新渲染,否则React组件将在每个生命周期重新渲染。在您的情况下,当您使用功能组件时,您可以利用这些组件来记忆这些组件,这意味着只有在传递的道具中的值发生变化时才会呈现这些组件。但是,当您有复杂的结构时,请注意这一点,因为默认的比较器只进行浅层比较
下面的代码片段演示了记忆化组件的使用,并说明了作为click事件处理程序的一部分正在执行的状态变化
const things=[
{“id”:0,“name”:“thing1”},
{“id”:1,“name”:“thing2”},
{“id”:2,“name”:“thing3”}
];
函数点击器({点击,名称,金额}){
返回单击的(名称)}>{name}:{amount};
}
//只在其简单道具更改时更新的记忆组件
常量ClickerDisplayMemorized=反应。备忘录(功能ClickerDisplay(道具){
常量{name,amount,index}=props;
log(`Updating ClickerDisplay${index+1}`);
返回{name}:{amount};
});
函数视图(){
const thingsWithAmounts=things.map((item)=>({…item,amount:0}));
const[state,setState]=React.useState(thingsWithAmounts);
//更新的回调,避免状态突变
函数updateAmount(索引,newAmount){
设置状态(state.map)((项目,i)=>({
…项目,
金额:(i==索引?新金额:项目金额)
})));
}
const createClicker=({name,amount},index)=>(
updateAmount(索引,金额+1)}/>
);
const createClickerDisplay=({name,amount},index)=>(
);
返回(
{state.map((项目,i)=>(
//此组件需要一个键,因为它是map()的一部分
-
{createClicker(项,i)}={createClickerDisplay(项,i)}
))}
);
}
ReactDOM.render(,document.getElementById('root'))代码>
/*这只是为了使此代码段中的控制台不包含组件*/
.作为控制台包装{最大高度:50%!重要;}
更新后重新渲染的所有子对象有什么问题?请更具体地说明问题所在。另外,如果您能提供一个@GhassenLouhaichi,那就太好了。我不认为这是错误的,但是有些孩子应该每100毫秒更新一次,所以如果我每次都重新播放每个孩子,那么性能损失将是疯狂的。在我看来,我的示例非常简单,可以理解。假设您知道每个子组件都应该在其支柱之一发生更改时进行更新,您是否考虑过使用?@GhassenLouhaichi在查找shouldComponentChange()之后,在实现挂钩和功能组件之前,它似乎是一个比较旧的解决方案。。我错了吗?它仍然在被积极使用,问题是,功能组件应该在您试图实现的行为本质上很简单时使用。当事情变得有点复杂时,比如在这里要实现条件重渲染的情况下,最好使用类。在您的情况下,我建议将ClickerDisplay
转换为一个类,并使用shouldComponentUpdate()
。