I am new to React JS and would like few ideas regarding implementing the side navigation.
We have Side Nav currently which gets generated from an API response in below structure.
A section may or may not have a subsection. Also, Subsection may or may not have a sub of sub-section. This can be infinite.
abc-SECTION
abcdef-SUB-SECTION
woirlew-SUB-SUB-SECTION
ABCDWER-SUB-SECTION
ABCDXDC
WERLLWWR-SUB-SUB-SECTION
xyz-SECTION
XYZSERF-SUB-SECTION
XYZlJIO-SUB-SECTION
owe-SECTION
abcdef-SUB-SECTION
ABCDWER-SUB-SECTION
slfjl-SUB-SECTION
We want to keep the tree structure as above but want to our tree structure to behave something similar to below link.
https://www.hindustantimes.com/interactives/aap-government-two-years-report-card/
We already have a side bar rendering implemented using recursive function. I am looking for scrolling behaviour.
Any guidance would be appreciated. What would be the good way to start with?
To create sidebar can create kind of recursive Component in reactjs.
class Tree extends Component {
render() {
return {
<div>
{this.props.children.map((child) => (
<div key={child.key}>
<span>{child.name}</span>
{child.children && <Tree children={child.children} />}
</div>
))}
</div>
}
}
}
In React to render a list you can have a separate function that takes a data structure as an input such as array or object and recursively calls itself to generate a UL, LI structure. Check this link out for recursively iterateing through an nested array of objects
For the scrolling behaviour you can usive javascript onClick event handler and window.scrollTop to calculate and scroll smoothly to that place alternatively theres a light-weight library for that behaviour Click here to Check it out
Related
I am using Gatsby as a frontend to a WordPress backend. I have successfully fetched the menu items but I now need to link them to the pages I have created. I have added the Menu Links in my Gatsbyconfig.js but I have no idea on how I can go about mapping it to the menu items at the same time as the menu itself. It ends up contradicting each other. Is this possible to do? I am quite new at graphQL. Never touched it till this project. Below is the GraphQl Query
{
allWpMenuItem(filter: {menu: {node: {name: {eq: "Navigation Menu"}}}}) {
edges {
node {
label
}
}
}
site {
siteMetadata {
title
menuLinks {
name
link
}
}
}
}
The label holds the name for each menu and the link holds the link to the pages I have created. I am trying to fix this into this bit of code
<div>
{props.allWpMenuItem.edges.map(edge =>(
<a href="#" key={edge.node.label}>
{edge.node.label}
</a>
))}
</div>
I am trying to query the menu links change the anchor tag to the link item and then point it to the menu link.
The short answer is that you can't, natively each query is a separate entity. However, you can combine queries using createResolvers, for further details check: https://github.com/gatsbyjs/gatsby/discussions/28275 (thanks LekoArts for the feedback).
However, you have a few approaches to bypass this limitation. Given that each query is transformed into a standalone JavaScript object, you can always manipulate them using native JavaScript filtering or doing whatever you need. The idea is to create an empty object and populate it with links and labels, in a single loop or using two different, then, in your component, iterate through this object instead of through the props like you are doing now.
I can't create a minimal example without knowing the internal structure or without knowing what's inside menuLinks.name.
By the way, if you are using internal navigation I would hardly suggest using <Link> component, among other things, using the #reach/router (extended from React's router) will only render the necessary parts of each component, creating smoother navigation than using native anchor tag, what will refresh all the page.
I'm trying to figure out how to animate moving react component from one to another. For example take very simple, yet interesting card game: you may place any card to a deck, or take top card from the deck.
To make it work, I have 4 classes - <Board> which holds two <Card Collection>: "Deck" and "Hand" components. In constructor, they generate CardModel items and render them via <Card> component. <CardCollection> component has special onCardClick prop which takes callback function. In my case it's onCardClick={/*this is equal to <Board>*/ this.transferCard("Hand")}
Board.transferCard takes clicked CardModel from state of one component and pushes it to another.
The problem is animation - I want card to fly, preferably through center (optional!) from old place to new. I am able to place the newly created Card in "new place" to the same place as old component, but, since i jsut strated to learn React, I'm not sure where exactly I should start. Wrap in ReactCSSTransitionGroup? pass "animate: from{x,y} to{x,y}" property to <CardCollection>?
So the full question is what is the most generic, controllable and "react" way to animate this situation?
JSFiddle base question version: https://jsfiddle.net/fen1kz/6qxpzmm6/
JSFiddle first animation prototype version: https://jsfiddle.net/fen1kz/6qxpzmm6/1
I don't like <this.state.animations.map... here. Also the Animation component looks like an abomination for me, I'm not sure this is the good architecture style for React.
The main mistake I did is try to mix render function with animation. No! Render should not contain anything related to animation (preferably not even starter values), while all the animation should happen after render. The only thing that bothers me is that i still should have state of animations in CardCollection just to throw it into creation of Card
Working example: https://jsfiddle.net/fen1kz/6qxpzmm6/4/
let animation;
if (this.animations[cardModel.id] != void 0) {
animation = this.animations[cardModel.id];
this.animations[cardModel.id] = void 0;
}
...
return <Card
cardModel={cardModel}
onCardClick={onCardClick}
animation={animation}
position={this.getCardPosition(i)}
index={i}
key={cardModel.id}
ref={cardModel.id} // prolly not needed
/>
You can try to use a package I made called react-singular-component, which might actually do what you need.
The component allows you to render a component server times and by a given priority only the highest one will render. Mounting and uncounting the given component will cause the next highest priority to render instead with an animation moving and wrapping the component from its last place and size to the new one.
Here is the Github page: https://github.com/dor6/SingularComponent
Just an idea: You could try to use jQuery animate for animation of moving some HTML element from one place to another. Once animation is complete there is a complete function property only then you could trigger your onCardClick.
Recently I started to refactor my Backbone web app with React and I'm trying to write interactive graph visualization component using react and sigma.js.
I roughly understood React's declarative paradigm and how it is implemented by render() method using jsx syntax.
But what gets me stumbled is a situation where I cannot define my React component declarativly.
It is because of the javascript-generated DOM elements, which only can be generated on componentDidMount() after the declarative DOM elements are rendered by render().
It makes me worried about both performance and buggy animations (my graph animates on instantiation time, which will be re-played on every render() calls in this situation)
My current code looks like:
...
render: function() {
return (
<div class="my-graph-visualization-component">
{/*
This div is defined declaratively, so won't be re-rendered
on every `change` events* unless `React`'s diff algorithm
think it needs to be re-rendered.
*/}
<div class="my-declarative-div">{this.props.text}</div>
{/*
This div will be filled by javascript after the `render()`
call. So it will be always cleared and re-rendered on every
`change` events.
*/}
<div class="graph-container MY-PROBLEM-DIV"></div>
</div>
);
},
componentDidMount: function() {
this.props.sigmaInstance.render('.graph-container', this.props.graph);
}
...
Is there any way to do something like
render: function() {
return (
<div class="my-graph-visualization-component">
<div class="my-declarative-div">{this.props.text}</div>
{/*
Any nice workaround to tell react not to re-render specific
DOM elements?
*/}
<div class="graph-container NO-RE-RENDER"></div>
</div>
);
},
so that my sigma.js graph component won't get re-instantiated with identical starting animation on every change on states?
Since it seems to be it is about handling non-declarative part of react components, any workarounds for this kind of problem will be appreciated.
The cleanest way is to define react sub-components and re-render what you really need instead of re-rendering the whole block
render: function() {
return (
<div class='myStaticContainerNotupdated'>
<SubComponentToUpdateOften/>
<MyGraph/>
</div>
)
}
The other solution could be to work on your graph and implement a singleton so your animation is only played once at the first render.
But really the easiest and cleanest thing I see is to create clean separate subcomponent and update them when needed. You never update the big container component just the subs one.
Hope it helps
You can use dangerouslySetInnerHTML. This basically tells React to stay away from it’s content and it wont evaluate/update it when doing it’s DOM diffing.
Before anyone press eagerly the close button, I already have looked the following question: ReactJS Two components communicating. My problem is exactly the third scenario developped in the current accepted answer.
I am using ReactJS to build something with two components. For HTML reasons (and presentation), i want my two components to be at two different places of the page.
For the moment, I have the following pattern, corresponding to scenario #2:
FooForm = React.createClass({
...
});
FooList = React.createClass({
...
});
FooManager = React.createClass({
...
render: function () {
return (
<div>
<FooForm ref="form" manager={this} />
<FooList ref="list" />
</div>
);
}
});
React.render(
<FooManager someProp={value} />,
document.getElementById('foo')
);
This gives something like:
<div id="foo">
<form>Form generated with the render of FooForm</form>
<ul>List generated with the render of FooList</ul>
</div>
However, i would like to have something like this:
<div id="fooform">
<form>Form generated with the render of FooForm</form>
</div>
<!-- Some HTML + other controls. Whatever I want in fact -->
<div>...</div>
<div id="foolist">
<ul>List generated with the render of FooList</ul>
</div>
The problem here is: how can I keep a reference in each component? Or at least the link Form -> List?
I tried to create the FooList before and pass the reference to the current manager, but I get the following warning/error:
Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. This usually means that you're trying to add a ref to a component that doesn't have an owner (that is, was not created inside of another component's `render` method). Try rendering this component inside of a new top-level component which will hold the ref.
The documentation says you can attach events to link two components which do not have a parent-child relation. But I don't see how. Can someone give me some pointers?
The Less Simple Communication lesson from react-training has a good example of how you can move actions & state sideways to avoid having to create an explicit link between related components.
You don't need to jump into a full Flux implementation to get the benefit of this approach, but it's a good example to lead you up to Flux, should you eventually need it or something like it.
Note that this requires you to model the relationship between the components based on changing state rather than explicitly passing a reference to a component instance (as you're doing above) or a callback bound to the component managing the state.
This would be the perfect use-case for a Flux type architecture.
What you want is someone FooManager to be able to trigger state changes in both components. Or, in fact, having the different components trigger, through Actions, state changes in each other.
The Flux Todo-App Tutorial illustrates your use-case perfectly!
After this, then you'd have the choices of using Facebooks implementation of Flux or the other gazillion ones.
My personal favorite is Reflux
I'm new to ember and am struggeling with the typical "how would one do that"-Problem. What I've got is fairly simple and I know how to do it, but my way is so complicated that I do not think it's correct.
The case:
<ul>
<li>{{link-to top-level}}</li>
<li>{{link-to another-top-level</li>
<ul class="submenu">
<li>{{link-to submenu</li>
</ul>
</ul>
What should happen is:
When a route is clicked, the corresponding list element should become active.
When a submenu is clicked the corresponding upper ul-element should get the class open
It's a fairly simple case with jQuery, but I understand that this is not scalable and abstracted and stuff.
Therefore I started with this approach:
Create a controller / template construct for the entire navigation to handle it's state (there are some other things I need to check as well, so it came in handy).
since ember adds the active class to the anchor tag I created a component to observe that:
Like:
export default Ember.Component.extend({
tagName: 'li',
classNameBindings: ['active'],
active: function() {
return this.get('childViews').anyBy('active');
}.property('childViews.#each.active')
});
Replacing the li elements with {{linked-list}} does indeed work.
But what next? Do I need to add another component to watch the component to watch the build in behaviour of active links? Do I have to write dedicated MVC-Classes for all the DOM Elements?
There has to be a simpler way, I think. I already created a whole lotta files for such a simple behaviour that I'm thinking I'm totally on the wrong track.
My gut feeling is: That is view logic and the view should just observe a few states in the template and that's it.
What's the leanest approach to the problem?
I don't know if I understand your question right, but why you want to add the class open to the corresponding upper element? It automatically get active assigned. And with correct CSS it should work as expected.
I have created a small example demonstrating what I mean. Please have a look and let me know, if that's the solution for you or what's your problem with this solution.
http://emberjs.jsbin.com/wifusosadega/7/edit
EDIT
Here is a Bootstrap flavored version: http://emberjs.jsbin.com/wifusosadega/9/edit .