Can anyone provide a stupid-simple example of an observable in ReactJS?
Basically I want to communicate a message from one component to another.
Google searches have send me down rabbit holes with RxJs, Redux, Hooks, shared memory, Class-based components, and other involved topics.
Take the following structure for example:
A
/ \
B C
/\
D E
I just need to send a true/false message from component D to C.
Is this inherently complex in React? tyvm, Keith :^)
RxJS
Redux-observable uses ReactiveX observables but I don't think it is the most commonly used method for React applications.
React state
React state (this.state or useState) only goes from parent to children so when D and C need state it has to be managed in a common ancestor which is A. This means that A needs to pass props to B that B doesn't need, only so B can pass it to C. This is called props drilling and is considered bad so not the best option.
Redux and react-redux
Redux store is an event store, you can dispatch actions (events) and reducers or middleware will act on these actions to update state (reducers) or cause side effects (usually done with middleware). The component(s) can use selectors to get data from state with useSelector(selectorFunction)
, previously HOC connect
was used but the hook is much simpler.
When an action is dispatched that causes state change then all the selectorFunction
functions are called by react-redux and if their return value is different than last run it'll re render the component where useSelector
was used.
Redux is a good candidate if you have to implement complex requirements as the CQRS/event store pattern makes it easy to separate actions (indicate what happened) from reducers (what to do when something happens) and you can query the store with selectors (reselect is commonly used).
Context
For applications that do not have complex requirements you may get away with using context, whenever you change a context the component that has useContext
will re render. Below is a simple example.
const BoolContext = React.createContext();
const BoolProvider = ({ children }) => {
//set bool message to true
const [bool, setBool] = React.useState(true);
const toggle = React.useCallback(
() => setBool((b) => !b),
[]
);
return (
// set value of context to {bool, toggle}
<BoolContext.Provider value={{ bool, toggle }}>
{children}
</BoolContext.Provider>
);
};
const D = () => {
const { bool, toggle } = React.useContext(BoolContext);
return <button onClick={toggle}>D:{String(bool)}</button>;
};
const C = () => {
const { bool, toggle } = React.useContext(BoolContext);
return <button onClick={toggle}>C:{String(bool)}</button>;
};
//removed E as it does not do anything to demonstrate context
const B = () => ( <D /> )
const A = () => {
return (
<BoolProvider>
<B />
<C />
</BoolProvider>
);
};
ReactDOM.render(<A />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>