简体   繁体   中英

React pass callback function to multiple child components

I'm trying to make a function that can get the position of its children on render so that it can re render them without overlap (they are absolutely positioned).

const ContentWrapper: React.FC<{article: Article.article.article}> = ({ article }) => {
  const [footnotePositions, setFootnotePositions] = useState<Number[]>([]);

  const updatePositions = (footnotePosition) => {
      setFootnotePositions([...footnotePositions, footnotePosition]);
      
  }

  useEffect(() => {
    // re position children... idk where to put this haven't gotten this far
  }, [footnotePositions])



  return (
    <>
      {article.map( (x, i) => (
        <span key={i}>
          { x[1]==='' ?
          <Line>{x[0]}<br/>&emsp;&emsp;</Line>
          :
          <>
            <Line>{x[0]}</Line>
            <FootnoteRef footnotePosition={updatePositions} />
            <Citation footnote={x[1]}/>
          </>
          }
        </span>
      ))}
    </>
  )
}

I can debug and see that the updatePositions function is correctly getting called, however this it doesn't set the state correctly (I assume because of the async nature setState()). The state is only set with the position of the last component that is rendered in the map() function.

How can I call setState from the callback function without overriding previous iterations?

Do I need to bind the callback function (how does that work in functional components)?

The state is only set with the position of the last component that is rendered in the map() function.

I think this is indicative of queueing state updates within a loop and using a value-based state update. IE Every foot note is mounted and invokes the footnotePosition | updatePositions callback with their position and overwrites the previous enqueued state value.

This is the situation you want to use functional state updates. A functional state update is sort of like a reducer function, but it only takes the current state as an argument. Pseudo code would look like this

setMyState(state => state + update)

Here is a Demo Codesandbox of mine to help illustrate the difference between the two types of state update.

编辑反应 - 定期和功能状态更新

Assuming the rest of your component logic is sound ( I have some uncertainty about the correlation of the article and footnotePositions arrays ) then I have the following suggestion:

Update your updatePositions function to use functional state updates.

const updatePositions = (footnotePosition) => {
  setFootnotePositions(positions => [...positions, footnotePosition]);
}

Not a big change, but now you can queue up multiple state updates and each update will update from the previously computed "next state" value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM