React how to pass data to parent navigation - reactjs

I have a navigation toolbar, with H1 in it.
I also various sub content for each page, as child component.
How can I pass the title information, from the child page component, to the parent navigation?
I've tried to use Context, but it only propagate from Parent to Childs.
Her is a simplified exemple:
const App = React.createClass({
render() {
return (
<div>
<toolbar>
<h1>{myTitleAccordingToPage}</h1>
</toolbar>
<main>
{this.props.children}
</main>
</div>
)
}
})
const A = React.createClass({
render() {
return (
<div>
Content for A page
</div>
)
}
})
const B = React.createClass({
render() {
return (
<div>
Content for B page
</div>
)
}
})

Extract state for your navigation either into a store, or somewhere else, and propagate that state to your application via props.
var page = {
title: 'foo'
otherData: ''
}
ReactDOM.render( <App page={ page }, element )
Now your top-level component knows about the state and can filter accordingly down to its children, for example, you might change your App render function to pass different bits of the application state down to different children i.e.
(I'm passing props explicitly here to show what is going on, and using a pure function to render, use a class and render method if that is more comfortable for you, the advantage of only ever passing props is that it is easier to make your functions pure, which has many advantages)
const App = props => {
<div>
<Toolbar title={ props.page.title } />
<Main otherData={ props.page.otherData />
</div>
}
Now you have created top-down data flow, making your application more predictable and possibly paving the way to use the pure render function to maybe give you performance boosts for free. The key with top-down data-flow is really making your application more predictable, which should translate into testability, and thus reliability, and makes hacking on your application easier.
The react-router module can help with creating structures like this. There is a small learning phase when adopting the module but the benefits for an app like the one you are creating should outweigh this and the speed of development once learnt may very well outweigh any learning outlay you invest into it.

Possible it's time to use Flex https://facebook.github.io/flux/docs/dispatcher.html#content
Usable approuch to two way data binding http://voidcanvas.com/react-tutorial-two-way-data-binding/
Original documentation to two way data binding, but mixin now is now supported https://facebook.github.io/react/docs/two-way-binding-helpers.html
( For mixin possible to use react-mixin npm package )
EDIT:
There is an opinion at comments that: "two-way data-binding is often a bad idea, and if your application makes more sense with two-way data binding then React should probably not be the framework to employ". So you need to rearrange your application architecture to avoid using two-way data binding if possible. Use flux instead.

Related

React Context always returns EMPTY

I have a Search parent component and a SideBar child component, I am trying to get context in SideBar, but everytime it returns empty.
I followed the tutorial exactly like: https://itnext.io/manage-react-state-without-redux-a1d03403d360
but it never worked, anyone know what I did wrong?
Here is the codesandbox link to the project: https://codesandbox.io/s/vigilant-elion-3li7v
I wrote that article.
To solve your specific problem:
When using the HOC withStore you're injecting the prop store into the wrapped component: <WrappedComponent store={context}.
The value of the prop store is an object that contains 3 functions: get, set, and remove.
So, instead of printing it, you should use it. For example this.props.store.get("currentAlbums") or this.props.store.set("currentAlbums", [album1, album2]).
This example is forked by your code: https://codesandbox.io/s/nameless-wood-ycps6
However
Don't rewrite the article code, but use the library: https://www.npmjs.com/package/#spyna/react-store which is already packed, tested, and has more features.
An event better solution is to use this library: https://www.npmjs.com/package/react-context-hook. That is the new version of the one in that article.
This is an example of a sidebar that updates another component content: https://codesandbox.io/s/react-context-hook-sidebar-xxwkm
Be careful when using react context API
Using the React Context API to manage the global state of an application has some performance issues, because each time the context changes, every child component is updated.
So, I don't recommend using it for large projects.
The library https://www.npmjs.com/package/#spyna/react-store has this issue.
The library https://www.npmjs.com/package/react-context-hook does not.
You pass the store as a prop, so to access it, you need this.props.store in your SideBar.
Not this.state.store
Create a wrapping App component around Search and Sidebar:
const App = props => (
<div>
<Search />
<SideBar />
</div>
);
export default createStore(App);
Now you can manipulate state with set and get that you have available in child components Search and Sidebar.
In Search component you can have something like:
componentDidMount() {
this.props.store.set("showModal", this.state.showModal);
}
also wrapped with withStore(Search) ofc.
and in SideBar you can now call:
render() {
return (
<div>
{"Sidebar: this.state.store: ---> " +
JSON.stringify(this.props.store.get("showModal"))}
}
</div>
);
}
and you will get the output.

How to globally disable/hide/replace a component by name in React?

I have a large React app and I have a few components that I would like to completely disable from a config or global level. Is there any kind of global hook that I can use that is called before any component is rendered? If so, I imagine I can check the name of the component and return null if the name is on the disabled list. How would you do this?
There are a lot of ways to do this:
React's Context API allows you pass props through every level of the component tree so you can use them as flags to enable/disable components. Should be used sparingly however.
Higher Order Components are basically just functions that return a component. You could wrap your components in logic to render them as needed.
Or of course you could use a global state manager like redux to set global states.
There are many ways to do this, so, I'll just describe one simple way: using references and updating the states accordingly.
Full working feature hide/showing sandbox online: codesandbox.io ReactJS Feature Hide/Show Demo
Defined are two classes, class Feature extends React.Component and class App extends React.Component. The render() for <Feature/> is...
render() {
if (!this.state.enabled) {
return <div />;
}
return (
<div className="Feature">
<h1>My Feature!</h1>
</div>
);
}
And the option for enabling/disabling a feature in <App /> would handle display/hiding like so...
handleOnClick(e) {
if (e.target.checked) {
this.feature.setState({ enabled: true });
} else {
this.feature.setState({ enabled: false });
}
}
Of course, you need to make sure that <Feature /> has the reference set...
<Feature
ref={instance => {
this.feature = instance;
}}
/>
If you need simplest solution just use browser global vars and check it in render.
render() {
if( window.globalFlag ) return null
return (
<div> feature content...
Drawbacks:
modifying component,
using global scope,
some unnecessary code can be run earlier (f.e. constructor) and later (f.e. componentDidMount).
Use HOCs - wrap your component - connecting with global store using redux or context API.
<FlagsProvider store={flagStore}>
<SomeComponent_1>
<SomeComponent_2>
<FlagsConsumer flag="someFeatureFlag">
<SomeFeatureComponent />
<FlagsConsumer/> connects to store (redux connect would be an inner wrapper - composing HOCs) and conditionally renders <SomeFeatureComponent /> (or null).
Of course HOC can pass received props to wrapped component - it can be functionally transparent.
Don't reinvent the wheel - use some ready module, read tutorials, google for sth suitable.
HOC can also play a role of A/B testing.

Backbone => React - Higher Order Components, inheritance and specialisation

I have a legacy Backbone app which I have begun to rewrite in React. The app has a main view containing two subviews, arranged vetically. The top panel displays some data, and the bottom one displays the result of some algorithm taking this data as input. Since I have many different data sources, each with a different algorithm applied to it, I have an abstract base View class, which I then subclass for each data source, adding, decorating and overriding methods as necessary. Somewhat like this:
// Base View.
const BaseView = Backbone.View.extend({
events: {},
initialize() {
this.subViewA = // instantiate subview...
this.subViewB = // instantiate subview...
},
generateResultData() {
// 'Abstract' method which should be specialised to generate data rendered by subViewB...
},
render() {
// render subviews...
},
});
// Derived View.
const Derived = BaseView.extend({
events: {
// event handlers...
},
add(a, b) {
return a+b;
},
// additional methods...
generateResultData() {
return {
result: this.add(2,2);
}
},
})
This results in a shallow hierarchy of many similar View classes. It's all terribly imperative, but it's a simple, intuitive and easy-to-reason-about pattern, and just works. I'm struggling to see how to achieve the same thing in React, however. Given that subclassing of subclasses of React.Component is considered an anti-pattern, my focus has naturally been on composition, and in particular Higher Order Components. HOCs (which I find beautiful, but unintuitive and often just downright confusing) seem to involve adding general features, rather than specialising/refining something more general. I have also considered passing in more specialised versions of Componenet methods through props. but that just means I have to use the same boilerplate Component definition over and over again:
// General functional component, renders the result of prop function 'foo'.
function GeneralComponent(props) {
const foo = this.props.foo || ()=>"foo";
return (
<div>
<span> { this.props.foo() } </span>
</div>
)
}
// Specialised component 1, overrides 'foo'.
class MySpecialisedComponent extends React.Component {
foo() {
return this.bar()
}
bar() {
return "bar"
}
render() {
return (
<GeneralComponent foo={this.foo} />
)
}
}
// Specialised component 2, overrides 'foo' and adds another method.
class MyOtherSpecialisedComponent extends React.Component {
foo() {
return this.bar() + this.bar()
}
bar() {
return "bar"
}
baz() {
return "baz"
}
render() {
return (
<GeneralComponent foo={this.foo} />
)
}
}
The above is a very simplistic case, obviously, but essentially captures what I need to do (though I would of course be manipulating state, which the example does not do, for simplicity). I mean, I could just do things like that. But I want to avoid having to repeat that boilerplate all over the place. So is there a simpler and more elegant way of doing this?
Generally, if a component is stateless and doesn't use lifecycle hooks, there are no reasons for it to be Component class. A class that acts as a namespace and doesn't hold state can be considered an antipattern in JavaScript.
In constrast to some other frameworks, React doesn't have templates that would need to map variables in order for them to be available in view, so the only place where bar function needs to be mentioned is the place where it's called. JSX is an extension over JavaScript, JSX expressions can use any names that are available in current scope. This allows to compose functions without any classes:
const getBar => "bar";
const getBaz => "baz";
const getBarBaz => getBar() + getBaz();
const MySpecialisedComponent = props => <GeneralComponent foo={getBar} />;
const MyOtherSpecialisedComponent = props => <GeneralComponent foo={getBarBaz} />;
An anonymous function could be passed as foo prop instead of creating getBarBaz but this is generally discouraged because of unnecessary overhead.
Also, default prop values could be assigned with defaultProps without creating new ()=>"foo" function on each component call:
function GeneralComponent({ foo }) {
return (
<div>
<span> {foo()} </span>
</div>
)
}
GeneralComponent.defaultProps = { foo: () => 'foo' };
IMO what is throwing you off isn't inheritance vs composition, it's your data flow:
For example, many of my derived views need to do custom rendering after the main render. I'm using a third-party SVG library, and the data rendered into the 'result' subview is derived from analysis of rendered SVG elements in the main data view above it
So what you're trying to do here is have a child update props of a distantly related component after render, correct? Like this?
// after the svg renders, parse it to get data
<div id="svg-container">
<svg data="foo" />
<svg data="bar />
</div>
// show parsed data from svg after you put it through your algos
<div id="result-container">
// data...
</div>
There's a lot of state management libraries out there that will help you with this problem, that is, generating data in one component and broadcasting it to a distantly related component. If you want to use a tool built-in to react to address this you may want to use context, which gives you a global store that you can provide to any component that wants to consume it.
In your example your child classes have data-specific methods (add, etc.). IMO it's more typical in react to have a generic class for displaying data and simply passing it down map functions as props in order to rearrange/transform the rendered data.
class AbstractDataMap extends PureComponent {
static defaultProps = {
data: [],
map: (obj, i) => (<div key={i}>{obj}</div>)
};
render() {
const { data, map, children } = this.props;
const mapped = data.map(map);
return (
<Fragment>
{mapped.map((obj, i) => (
children(obj, i)
))}
</Fragment>
);
}
}
// in some other container
class View extends Component {
render() {
return (
<div>
<AbstractDataMap data={[1, 2, 3]} map={(n) => ({ a: n, b: n + 1 })}>
{({ a, b }, i) => (<div key={i}>a: {a}, b: {b}</div>)}
</AbstractDataMap>
<AbstractDataMap data={[2, 4, 6]} map={(n) => (Math.pow(n, 2))}>
{(squared, i) => (<div key={i}>squared: {squared}</div>)}
</AbstractDataMap>
</div>
);
}
}
IMO this pattern of using an HOC to abstract away the labor of explicitly using .map in your render calls (among other uses) is the pattern you are looking for. However, as I stated above, the HOC pattern has nothing to do your main issue of shared data store across sibling components.
Answering my own question, which I've never donw before...
So my question really arose from a concern that I would need to refactor a large, imperative and stateful codebase so as to integrate with React’s composition-based model (also with Redux). But it occurred to me after reading the (very insightful and helpful) responses to my question that my app has two parallel parts: the UI, and an engine which runs the algorithms (actually it's a music analysis engine). And I can strip out the Backbone View layer to which the engine is connected quite easily. So, using React’s context API I've built an ‘AnalysisEngineProvider', which makes the engine available to subcomponents. The engine is all very imperative and classically object-oriented, and still uses Backbone models, but that makes no difference to the UI as the latter has no knowledge of its internals - which is how it should be (the models will likely be refactored out at some point too)...
The engine also has responsibility for rendering the SVG (not with BB views). But React doesn’t know anything about that. It just sees an empty div. I take a ref from the div and pass it to the engine so the latter knows where to render. Beyond that the engine and the UI have little contact - the divs are never updated from React state changes at all (other components of the UI are though, obviously). The models in the engine only ever trigger updates to the SVG, which React knows nothing about.
I am satisfied with this approach, at least for now - even if it's only part of an incremental refactor towards a fully React solution. It feels like the right design for the app whatever framework I happened to be using.

How to transfer props to the deepest component fast?

I render React on a server.
I have a common chain of three components. I need to pass a units object (just plain js object {name: 'example.com'}) to the deepest component <Foo /> in the chain from the most outer component <FooBox />. For now I have to pass my unit object down through every component as a this.props.units. I doesn't look nice, it looks like some bad practice to me:
// my-react-components.js file
var FooBox = React.createClass({
render: function() {
return (
<div>
// here I pass 'units'
<FooList data={this.props.data} units={this.props.units}>
</div>
);
}
});
var FooList = React.createClass({
render: function() {
return (
<div>
// and here I pass 'units'
<Foo myId={this.props.data[0]} units={this.props.units} />
</div>
);
}
});
var Foo = React.createClass({
render: function() {
var units = this.props.units; // and only here I use `units`
return (
// only here I need `units`
<div dangerouslySetInnerHTML={{__html: units[this.props.myId].name}}>
</div>
);
}
});
On server-side my code is as follows (a Node.js app):
var React = require('react');
var ReactDOMServer = require('react-dom/server');
var FooBox = require('../my-react-components.js');
var data = [...some data here...];
var units = {name: 'example.com'}; // this is my 'units' object
var html = ReactDOMServer.renderToString(React.createElement(FooBox, {
data: result,
units: units // so 'units' comes yet from here
}));
My question is:
Is it the only way to get units in <Foo />? Only by passing it down the whole chain as a props? Is there a way to get units in <Foo /> easier, avoiding step-by-step props passing?
you can use context instead of props.It lets you pass data through the component tree without having to pass the props down manually at every level https://facebook.github.io/react/docs/context.html
For fast pass down {...this.props}.
For clear logic I think we must pass it down
In my opinion, the large degree of redeclaring and reassigning the same properties down the component hierarchy tree is one of the more irritating features of React. It could be argued that this is a strength: the data flow is explicit and makes your application easy to reason about. But personally I find such repetition to be jarring.
Certainly context, as mentioned by vistajess, is one solution. But I am loath to invest much in an experimental API.
Another solution is to use Flux and have store listeners spread across different components. (In Redux for example, these would be contected components.) Of course this somewhat increases the complexity of your components.
Or finally you can just grin and bear it. (It's generally what I do.) Constantly re-typing the same properties may be annoying, but as far as code smells go its pretty minor. Bear in mind too that React is still fairly new and its API is rapidly evolving. In time, surely some solution to this problem will be adopted. (The mainstreaming of context perhaps?) For now, be comforted by the fact that React's weaknesses are far outweighed by its strengths.

How can I create a list of UI elements, each aligned differently?

Say I want to create a list of UI elements, and I want each element to align differently. I was imagining something like:
<List>
<Button Alignment="right"/>
<Panel Alignment="left"/>
<Video Alignment="center"/>
</List>
How is this best achievable? Preferably by not adding special handling of the alignment property to each child element.
There are a number of ways to accomplish something like that in React, with no particular way necessarily being the "best."
I'd definitely recommend looking at:
http://facebook.github.io/react/docs/getting-started.html
Here's one idea using a simple mixin.
var List = React.createClass({
render: function() {
return (
<div>
<Button alignment="right" />
<Panel alignment="left" />
<Video alignment="center" />
</div>
);
}
});
var Button = React.createClass({
mixins: [AlignmentMixin],
render: function() {
return (
<Button { ... this.props } className={ this.renderAlignment() } />
);
}
});
var AlignmentMixin = {
renderAlignment: {
// whatever you'd like, just an example
// of constructing a class name called box-right/left/center
return "box-" + this.props.alignment;
}
}
There isn't an equivalent to an Angular directive that could be applied globally to all types. React takes a different approach and by design (currently) expects that components present a well-known interface and cannot be arbitrarily extended by the consumer of the component. It means that a component in ReactJS is only what it says it is and can do, and a parent component can only affect its behavior by setting properties on the component instance.
In the example I provided above, I've explicitly added the "alignment" mixin to the Button. Without it, the button would not have the feature of alignment.
Of course, you could just add the necessary code to the Button to do the alignment if there wasn't a general pattern that could be applied as simply as I have shown above.
Some might not even use a mixin as they would rather have the code that "is a" Button be only in a file called, Button.js (for example). The UI and behavior is not spread around multiple files potentially as it might be in an angular app (where directives may be in different files and difficult to discover what might be applied to any given element).
In fact, from the "why react page":
Since they're so encapsulated, components make code reuse, testing,
and separation of concerns easy.

Resources