Reactjs React Hooks-与多个动态组件共享父状态

Reactjs React Hooks-与多个动态组件共享父状态,reactjs,Reactjs,我目前正在构建一个带有挂钩的React应用程序。 我有一个组件(视图),它从某处加载数据并动态生成组件(Clicker、ClickerDisplay),一方面显示数据,另一方面交替显示数据 这个应用程序基本上可以运行,但我关心的是它的性能。我的状态每100毫秒更新一次,如果所有内容都在更改后重新提交,这将是一个巨大的开销 是否可以只重新启动应该更改的组件 另一件对我来说很难看的事情是我更新状态的方式设置状态([…状态])有没有更好的方法 旁注: 在我的示例代码id中,我目前只将项属性传递到子组件

我目前正在构建一个带有挂钩的React应用程序。 我有一个组件(视图),它从某处加载数据并动态生成组件(Clicker、ClickerDisplay),一方面显示数据,另一方面交替显示数据

这个应用程序基本上可以运行,但我关心的是它的性能。我的状态每100毫秒更新一次,如果所有内容都在更改后重新提交,这将是一个巨大的开销

是否可以只重新启动应该更改的组件

另一件对我来说很难看的事情是我更新状态的方式<代码>设置状态([…状态])有没有更好的方法

旁注:

在我的示例代码id中,我目前只将项属性传递到子组件中,但我计划将整个项传递到子组件中

我还想保留父组件中的主要状态,因为应用程序的状态应该被建立并保存到一个大的JSON对象中

数据

//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()