React App - materialize-css doesn't initialize on first render - reactjs

I am building a 'Add Item' functionality with React and materialize-css. For some reason, the materialize-css components are not being initialized when i first navigate into the page they are on. They do initilize though after I refresh the page. I spent several hours trying to figure out the problem but couldn't find what i did wrong. I installed materialize-css via npm and here is my code where i initiliaze the materialize-css components:
componentDidMount() {
var context = this;
document.addEventListener('DOMContentLoaded', function() {
var elemsTwo = document.querySelectorAll('select');
var instancesTwo = M.FormSelect.init(elemsTwo, {});
var elemsThree = document.querySelectorAll('.timepicker');
var instancesThree = M.Timepicker.init(elemsThree, {});
});
}
Like I said it does work fine after refreshing the page, but when just navigating into the page, it doesn't work. Below are the screenshots on how the page looks before and after refreshing (refer to fields 'Gender' and 'Spoken Languages' on screenshots). Thanks in advance.

Its a bad practice to use React while using DOMContentLoaded on your own. Your main problem is, that DOMContentLoaded is fired when your content is ready, but this does not mean that React has done its initialisation. Also, DOMContentLoaded is not fired when you navigate between pages using React.
You may use a library that already closes this gap, like https://material-ui.com/.
If you want to stay with your concept, you have to call the code you run in your componentDidMount also when your navigator changed the page.

Related

How do I use custom Javascript in Next js

Coming from React, i am really confused. In pages/index.js, suppose I have a button with onClick listener, and clicking on that button will log "you clicked" in the console. How do i implement this? I want that page to be statically generated and also give that button some functionality.
The reason I am having a lot of trouble is because in React tutorials or even in my projects, if i needed some functionality i'd do this:
function handleClick() {
document.body.style.background = "black"
console.log("you clicked") //nothing is logged in console
}
export default function App() {
return(
<button onClick{() => handleClick}>Click Me</button>
)
}
I was gonna use this Next.js to see how state works. But I encountered a different problem. Unless I use inline function in onClick, it doesnt work. If I use a seperate handleClick function, the DOM doens't even show that I had an onclick event. I learned that's because Nextjs is rendered server side, so it doesnt have access to DOM and console etc. Then how do i do this?
I just transitioned from React, and in every tutorial, those guys would use handleClick func or whatever to handle events and stuff. But I couldnt find a solution to do this in Next, how does everyone handle this then? Because pages have interactive buttons right? Are those pages not statically generated then?
You forgot call function handleClick:
<button onClick{() => handleClick()}></button>
the same way you do it in react with your onClick function
Static generation pre-rendering does not change the interactivity of any page, check the following from Next.js documentation :
Each generated HTML is associated with minimal JavaScript code
necessary for that page. When a page is loaded by the browser, its
JavaScript code runs and makes the page fully interactive. (This
process is called hydration.)
https://nextjs.org/docs/basic-features/pages

React route url and view changes but component function still active. Why?

I have an event function that is triggered by a button click. It's purpose is to keep the body position fixed keeping it from scrolling until you click the button again to close/toggle it off.
It works fine but, when I click to another page without toggling it off it is still active. Meaning the new page will not scroll because the body position is fixed.
I am new to React FYI
My code:
bodyFixed(event) {
document.body.classList.add('body-fixed');
}
bodyRelative(e) {
document.body.classList.remove('body-fixed');
}
I am using react-static withRouteData, RouteData, Router and I have no issues on those pages. But, on pages like an article page where the route doesn't change the same way. This is where I am seeing the problem.
Is there something I can wrap it with so that when I click to a new page it goes back to default?
Please first ask if you need more information and I will gladly add more.
Yes, you can call bodyRelative method in componentWillUnmount lifecycle hook to unset the class. Something along those lines:
componentWillUnmount() {
this.bodyRelative()
}

React Component: Foundation Modal (Reveal) won't open

So I've just started learning React and Redux, so I apologize if this is a very noobish question. But I've emptied my Google quote, and can't find anything that helps me.
My problem is: I work on a site with React, Redux, and Foundation 6. One of my React components have a link, that when clicked, should open a Modal with a specific warning for that link. So I've created a component with my modal markup:
ComponentModal.js:
import React, { PropTypes } from 'react';
const Modal = () => (
<div className="reveal" id="exampleModal1" data-reveal>
<h1>Awesome. I Have It.</h1>
</div>
);
export default Modal;
The component with a link renders some stuff, but basically have a
<a data-open="exampleModal1">Click me for a modal</a>
tag in it's render.
And although inspecting the page confirms that the markup for the modal exists, nothing happens when i click the link.
If I move the popup from the component, and into the DOM, the link works.
Some trial and error shows me, that if i manually run $(document).foundation(); in the console when ComponentModal is rendered, the popup works as intended.
So my question is kinda two questions:
1. How do I, in Redux, run $(document).foundation(); when my ComponentModal is done rendering? Maybe I'm wrong, but I don't have the componentDidMount() method available to me, where it might make sense to make that call?
2. Is this a totally wrong way to go about it?
Hope it's not too confusing and not too dumb a question :)
FYI, this question/solution has nothing to do with REDUX!
The problem is that you're trying to use React AND Jquery to make your page do cool things.
You should really choose one or the other.
$(document).foundation() is a Jquery library.
Instead you should use something like React Foundation which removes the jquery dependency and gives you foundation components built with react.
You can do $(document).foundation() in React inside componentDidMount of the component that has the reval modal or better yet You can do this inside componentDidMount of the top most partent in your app.
componentDidMount in React runs once after all the DOM nodes related to that component is mounted. What $(document).foundation() does, if it runs inside componentDidMount, is that it binds event handlers on the elements that have foundation realated attributes like data-dropdown or data-reveal.
componentDidMount() {
$(document).foundation();
}

Handing cold navigation to internal URL in Backbone?

I'm wondering how people handle the following case in Backbone: usually when a user navigates to the root of your app, a certain set of data is loaded from the backend, processed right away and then displayed in the DOM.
There are links in the app that will navigate you to different sub-sections of it. The router catches the navigation and replaces the current page with whatever page you navigated to, all based on the same data that's already been fetched.
The problem is that the user could bookmark that internal/secondary URL and navigate to it "cold", as in before the data has had a chance to be fetched, without going through the root URL. Is there an idiomatic/conventional way of handling that situation (in the router, I'm assuming)?
One way is, in the various router path-handling functions, to always call a method that will check if there's sufficient data to complete the operation, and if not, fetch it and then proceed?
Backbone won't hit the initial route in your router before you call Backbone.history.start, so you can delay it until you've done the necessary setup. I typically define a start method on my application's main router. Looks something like:
var AppRouter = Backbone.Router.extend({
start: function() {
//init code here
something.fetch({success: function() {
//only call history start after the necessary initial setup is done
Backbone.history.start();
}});
}
});
And then start the application using that method:
window.app = new AppRouter();
window.app.start();
It's good to remember that there is nothing confining you to build your application using only the predefined pieces provided by Backbone. If your startup code is heavy, it may not belong to the router. In such case you should define a helper function to encapsulate the startup logic, and leave the router out of it altogether:
//startup.js
function startup(onComplete) {
//do initialization stuff...
onComplete();
});
//main.js
startup(function() {
Backbone.history.start();
});

Backbone Marionette, Render Region if not already rendered

So I want to render a sidemenu itemview only if it's not rendered already. This is so unessecary I don't force unessecary re-rendering.
I have figured a solution to render a view if not rendered in a region already.
Take the following example in a controller object called by a router.:
Admin.showIndex= function(){
if (!MyApp.layout.sidepanel.currentView || !(MyApp.layout.sidepanel.currentView instanceof AdminSidePanel)){
MyApp.layout.sidepanel.show(new AdminSidePanel());
}else{
alert("Already rendered sidepanel!");
}
// More stuff!
}
Is this a good way to do it? It works like this:
If I F5 refresh the page /#admin , the sidepanel is rendered.
If I go in forexample /#admin/submenu and back to #admin, sidepanel is not rendered again.
Looks good to me. I've used similar logic in my project.
I prefer this approach over explicitly maintaining a global state variable in MyApp.

Resources