I have a react component for a list of data comprised of two sub components
<List>
<SortingAndFiltering data={this.state.data}/>
<RowsDisplay data={this.state.data}/>
</List>
One subcomponent handles sorts and filters and the other renders the actual bulk of the data.
When I perform a sort on the props.data inside SortingAndFiltering the event isn't propagated up the chain.
Whats the correct way to signal that a consumer of a prop has made a change to this prop?
React doesn’t do two-way data bindings by default and for good reasons.
However, there is an add-on called ReactLink that could be of use: http://facebook.github.io/react/docs/two-way-binding-helpers.html
If you are using Backbone as data models, there are mixins that provide listeners for model changes that can re-render the app when signals are received from anywhere in the hierarchy.
To dig deeper regarding unidirectional data flow, I recommend this video that explains the Flux concept used by Facebook: http://facebook.github.io/react/docs/flux-overview.html
checkout http://facebook.github.io/react/docs/thinking-in-react.html step 5,which is similar to yours.
Related
I have multiple view in my application, I need helpl in how to use reusable component effectively ? Is it ohk if I create viewspecific component from reusable component ? - Generic Tree View . For users View which will render with user specific data and actions .
I have written re useable component in my react app.Which I have to use it with different data and action is it ohk to creat new component which use resuable component and provide data related to that ?
i.e
Component - DepartmentTree which renders and some functions related to Department. So finaly I will render
Component - usersTree same way here it calls and methods related to users . In the users view I will render
It's definitely OK to create a view-specific component that renders a reusable component. You could let this depend on how big your page is. If it includes a lot of components, then do split them up in view specific components.
About the data, you have a few options... First of all you could map the data response to a general structure that your TreeView component can read, so you only need to pass some props to the TreeView component. You could do this in the redux reducer.
If you require specific data different behaviour, but you still want to use the reusable TreeView component, you could think about creating a Higher Order Component. This component will wrap your reusable component and add some specific logic to it. You can read about it and see some good examples here: https://reactjs.org/docs/higher-order-components.html
The most important thing I always keep in mind: It's not always about how you finally do it, it's about keeping it simple, understandable and consistent.
I know It may sound like a dumb question, But I am not able to get this solved in my head. Please bear with me.
In case when we use a state management system in React like Redux / Mob X, I guess the main purpose of these state management techniques is to provide a single source of Data and a more structured approach of updating it.
Say, I am Using a state management library(MobX) for React, And suppose I have a parent component which makes an http API call and updates the MobX store with the API response. Now I need that data in one of child/nested components.
My Question is, Should I pass that data as a prop to child component or should I enable child component to connect with Central Store and directly get that data ?
by connecting the child to store, I am turning the Child into a class component, which is making it more heavy and React optimisations may not apply. I am defeating the whole purpose of a functional component.
Awaiting replies.
Best Regards,
Lalit
This completely depends on the situation. I would suggest splitting your components up in 2 parts:
Components that could be re-used in other projects
(Higher level) Components that are so specific to this project that they probably never will be re-used.
For components of category 1, I would suggest not using mobx store directly, but instead make pure react components. (eg think of a dropdown, or an ajax dropdown component).
For second part components (think of, header, footer, section components specific for your website). just make them directly interact with the Mobx store, so that you can way quicker code what you need (instead of constantly having to prop everything).
addition
For components of category 1 you can always wrap them with the #inject() method. This way for example you could turn a dropdown component into a UserDropdown component that uses the mobx store for its state. (The inject method injects mobx state as props in the component).
const UserDropDownComponent = mobx.inject(stores => ({users: stores.userStore.users}))(DropDownComponent);
// usage:
<UserDropDownComponent />
Warning
For pure components wont always see changes of mobx state. To Fix this you need to wrap the component in an #observe annotation. Or you have to inject the props by wrapping it into: mobx.toJS(yourMobxStateProperty)
My app is structured as follows:
<App>
<SelectItems/>
<Tabs>
<Tab> <Window1> </Tab>
<Tab> <Window2> </Tab>
</Tabs>
</App>
The App has a state element called allItems, and SelectItems is used to narrow this down to App.state.selectedItems. The tabs work in a way that only one of the tabs shows at a given time, it's a component from React-Bootstrap.
The Window1 and Window2 display data that depend on the selectedItems, the data (let's call it data1 and data2) is obtained via a computationally intensive api call. Here's the problem. The cleanest way to do this while thinking in React is to "pull the state up", so that data1 and data2 are updated from App whenever the selectedItems change, and the data is then stored in the state of App and passed down to the tabs. This however is inefficient, because only one Window is showing at a given time, so I'm wasting time updating data that I'm never showing. In my actual app I've got many tabs, so it's a real problem.
What's a way of fixing this? I want the Windows to update whenever the App.state.selection changes, and I looked at static getDerivedStateFromProps(props, state) but it looks like (but I'm not sure) that this function won't work because the state updating would be asynchronous, as it requires an API call.
Are there general strategies one can use in this situation?
Thanks!
You have a couple of options, the first one is the one most people would recommend (because it is a popular option) and that is to use Redux to manage your application state.
Redux will allow you to keep all your data in a separate "store". Then from your components you can connect to the store and access the data which is relevant to them. Those components should only update when the data they are interested in is changed, any other changes to the store will be ignored.
There are a lot of good tutorials on using Redux and React together which you can find online - apparently the ones on egghead are pretty good, you can maybe try this one to get started.
Your other option might be to use a PureComponent so that you can limit when your component will re-render to only when it's props or state change rather than if the parent re-renders. You can read about this here. It's actually similar to the previous solution are the connect function provided by the react-redux library to connect to the Redux store wraps your component in a PureComponent.
I'm building an application where I would like to provide separate views for same data.
In my current implementation, data is obtained by web service call and persisted in state of App component in App.js. App component hosts (renders) another component called StackEditor, which acts as a view for this.state.components in App component.
UI elements rendered by StackEditor can be moved around, and to synchronize state of App I do it as below:
<StackEditor
components={this.state.components}
onLocationChanged={this.handleLocationChanged} />
In handleLocationChanged I update the state:
handleLocationChanged(e, data) {
this.setState(prevState => {
// event data copied to state here
return {components: prevState.components};
});
}
As state is now updated, this forces StackEditor to be rendered again, as its property components is bound to state as components={this.state.components} (see in the code snippet above).
This all works, but now I started questioning if I'm doing it right.
Q1: Should I be using state instead of props?
It seems that location of component is mutated in principle, although from StackEditor point of view, it is immutable (I can decide that change is invalid and not to update the state in event listener).
Q2: Is it possible to share part of the state between 2 components in React?
If I somehow convert StackEditor from getting components from state instead of props, will I get notification on state changed by child component (StackEditor) in my parent component (App)?
Q3: Also, are props more convenient to use than state in general?
When I created another component following HOC guidelines (https://reactjs.org/docs/higher-order-components.html) I discovered that props are easily forwarded to "wrapped" component, but not state. If I provide a function to call back via property (as I did above), "wrapped" component can easily call it, without even noticing that it's "wrapped". I don't see how I can easily notify "wrapped" component about state change in "wrapper", without writing some extra code.
If you imagine your application to be a tree of components in a well designed app it's usually like this:
the leafs are stateless components . They decide how data is rendered.
the nodes are stateful components. They decide which components and data to render.
Q1: Should I be using state instead of props?
It depends on which category of components you have (node or leaf).
Q2: Is it possible to share part of the state between 2 components in
React?
If you feel that your app has a lot of state that mutates and needs to be used by several components spread over your tree you usually start to introduce an external state management library (e.g. redux). Components can subscribe to your store and become stateless as your store now handles the state.
Q3: Also, are props more convenient to use than state in general?
They solve different problems so you can't really say that. A stateless component is usually easier to understand but has no capabilities to control anything.
Also read Identify where your state should live and When to use redux.
All that is only a rule of thumb. A lot of the time you will have components that have both state and props because they control parts of your app but delegate other parts to their children.
This all works, but now I started questioning if I'm doing it right.
As far as I can see from the code you provided this looks pretty much as it has to.
Tools I'm Using: Reactjs 0.14.7, react-router 2.0.0 (Flux Pattern)
Note: I tagged Redux, just cause I got a hunch(I haven't used it) that what I'm experiencing might be one of the reasons people rave about it.
I understand that react-router already manages which parts of the
component tree are currently in view and renders the components based on the state of the current view tree.
Question:
But what if, based on the components in view, one component needs to know what other components are also in view and behave differently depending on what other components are in view(the view state)? What strategy would you suggest to allow components to be aware of the other components in view?
My Current Solution:
I currently am trying to use the URL to infer this global state, and even parsing it and putting it into a store in order for components to be aware of the view state by listening to changes from that store.
My Issue With This Solution:
In a nutshell managing that view state with a store becomes a highly entangled process with extra actions sprinkled all over the code.
1) Actions must be called for any user event that change the route.
2) Action need to be fired when navigating outside of components(I think its much cleaner to keep action firing in components(feel free to debate that one).
3) You must also consider the back button(currently using react-router onEnterHooks to catch when that happens).
Yet I really like the concept of encapsulating the view state because I can imagine that it creates a nice mental model and also smarter components, but just parsing the current URL and using a utility file to determine the current view state when needed, seems like a much easier/cleaner solution to manage then a store that contains the current view state.
Components should never need to know what other components are being rendered, that's one of the fundamental concepts of React. You're trying to extract the "view state" from your component tree, when your component tree should be determined by your state. If you're already using Flux, you need to keep that information in the store, where it will be made accessible to any component that subscribes.
Flux isn't about making development easier or faster for an individual, it's about enabling practices that make it easier to keep a mental model of what an application is doing. This might come at the expense of some simplicity.
Redux is a refinement of Flux that combines the multiple stores that can be subscribed to individually with a single large state tree, with different parts of the tree created by different "reducers" -- functions that take a state and an action and return a new state. It is exactly "a store that contains the current view state." What you describe is also a pretty good description of the type of development common in hacked together jQuery applications, the type of development React seeks to avoid.
I think the core of your misunderstanding falls into how React component's should be layered. It's a tricky topic, and re-aligning your thought process to accurately understand what is a state vs. prop in your model, is a unique challenge.
But the solution to this problem you are facing is simply to order your components more 'correctly'.
At a high level, each component should only care about the props that are passed to it, and not about anything else whatsoever. However, which props are passed are determined by it's parent Component. As a result, that parent can make those decisions, which then have an end result in the child.
As a simple but practical example;
var Parent = React.createClass({
funcA: function(){
this.setState({propB: 'something new!'});
},
render: function(){
return (
<div>
<ChildA propA={this.state.propA} funcA={this.funcA} />
<ChildB propB={this.state.propB} />
</div>
);
}
});
With this layout of concerns, ChildA is capable of handling user input, passing it to funcA which then impacts ChildB. But all of this happens without the Child components knowing anything about one another whatsoever.