react hook多次setstate被合并怎么处理?

Twisted
  • 373

父组件在一个函数中接收三个子组件的回调,将三个回调接收的值作为一个对象存储起来,初始化的时候都会触发,现在只能保存最后一次回调的值,react将三次setstate合并了,这种情况怎么处理

// 父组件
const [obj , setobj] = useState({})

function cb(name, value) {
    const data = {...obj}
    data[name] = value
    setobj(data)
}

<A  change={cb}/>
<B  change={cb}/>
<C  change={cb}/>
// A组件

useEffect(() => {
  cb &&cb(x, y)
}, [])

// B组件

useEffect(() => {
  cb &&cb(a, b)
}, [])

// C组件

useEffect(() => {
  cb &&cb(e, f)
}, [])

现在父组件只能接收到最后一次的值,求大佬们帮忙!!

回复
阅读 824
2 个回答

setobject的参数是个obj,需要使用function回调来引用之前的值。关键代码:
setobj((prev) => ({...prev, ...data}))

const { useEffect, useState } = window.React

const A = ({cb}) => {
  useEffect(() => {
    cb && cb('x', 1)
  }, [])
  return <div>component A</div>
}

const B = ({cb}) => {
  useEffect(() => {
    cb && cb('b', 1)
  }, [])
  return <div>component B</div>
}

const C = ({cb}) => {
  useEffect(() => {
    cb && cb('c', 1)
  }, [])
  return <div>component C</div>
}

const App = () => {
  const [obj , setobj] = useState({})
  const cb = (name, value) => {
    const data = {...obj}
    data[name] = value
    //setobj(data)
    setobj((prev) => ({...prev, ...data}))
  }
  return <div>
        <A cb={cb}/>
            <B cb={cb}/>
            <C cb={cb}/>
    <div>obj: {JSON.stringify(obj)}</div>
  </div>
}

ReactDOM.render(<App />, document.querySelector("#app"))

可在线查看输出效果

另附一张回答该问题用到的工具图,欢迎大家在Segmentfault中使用RunJS。

示例: https://codesandbox.io/s/vigi...

import "./styles.css";
import { useState } from "react";
import A from "./A";
import B from "./B";
import C from "./C";

export default function App() {
  const [state, setState] = useState({});

  const onChange = (k, v) => {
    setState((prevState) => ({
      ...prevState,
      [k]: v
    }));
  };

  return (
    <div className="App">
      <A cb={onChange} />
      <B cb={onChange} />
      <C cb={onChange} />

      <div>{JSON.stringify(state)}</div>
    </div>
  );
}

A 组件(B, C组件类似):

import { useEffect } from "react";

export default function A({ cb }) {
  useEffect(() => {
    cb && cb("A", "1");
  }, []);
  return <div>Component A</div>;
}
宣传栏