I'll show two styles below, and you'll want to choose depending on how much the components' logic relate to each other.
Style 1 - Relatively related components can be created with callback references, like this, in ./components/App.js
...
<SomeItem
ref={(instance) => {this.childA = instance}}
/>
<SomeOtherItem
ref={(instance) => {this.childB = instance}}
/>
And then you can use shared functions between them like this...
this.childA.investigateComponent(this.childB); // call childA function with childB as arg
this.childB.makeNotesOnComponent(this.childA); // call childB function with childA as arg
Style 2 - Util-type components can be created like this, in ./utils/time.js
...
export const getTimeDifference = function (start, end) {
// return difference between start and end
}
And then they can be used like this, in ./components/App.js
...
import React from 'react';
import {getTimeDifference} from './utils/time.js';
export default class App extends React.Component {
someFunction() {
console.log(getTimeDifference("19:00:00", "20:00:00"));
}
}
Which to use?
If the logic is relatively-related (they only get used together in the same app), then you should share states between components. But if your logic is distantly-related (i.e., math util, text-formatting util), then you should make and import util class functions.