I have a rather simple question about React, but I wanna see what the best practice is for this kind of situation.
How do you change the body background color, according to the page you are in? Do you set a CSS rule for the body background color in a CSS file for each page and import it in the component? Will the above work or do I need to add a CSS class to the body tag using componentDidMount, and remove it in componentWillUnmout?
Which one is the preferred way? I noticed that if you imported some CSS in one page, it will remain active even after you navigate to a new url. So, maybe I need to use componentDidMount/componentWillUnMount, is that correct?
Yes,we can change the background-color of body based on the route change.Determine the page you are in by using componentWillReceiveProps or componentDidUpdate lifecycle method and get the route name using props.location.pathname provided by react-router-dom.If your route composes of params,then just replace the props.location.pathname by props.match.params.customparam
componentDidMount(){
document.body.style.background = "red";
}
componentWillReceiveProps(nextProps){
if(this.props.location.pathname !== nextProps.location.pathname){
const currentRoute = nextProps.location.pathname;
switch(currentRoute){
case "\a": document.body.style.background = "blue";
break;
case "\b": document.body.style.background = "green";
break;
default : document.body.style.background = "red";
}
}
}
Related
I have avatar with animations, like flying, floating, eyes, etc. and perform specific animation based on keycode mapping with specific animation.
to perform specific animation on specific key, i have created custom animation component as follow schema:
schema: {
keyCode: { default: stopAllAnimation }
}
and put that element and component in network schema:
{
selector: ".AvatarRoot",
component: "own-animation"
}
Locally/Individually it is working fine but in NAF I am facing the syncing issue like play specific animation not sync in other tab/screen.
Any one know how avatar animation works in network a-frame? and cloud be possible to sync perfectly.
You need to make things with a-frame schema and register component with a-frame extras included to make animation from gtlf/glb models.
The flow is like you need to set the register component with clip name in local JS file like this
let currentKeyDown = null;
document.addEventListener("keydown", (e) => {
currentKeyDown = e.which;
const avatar = document.querySelector("#local-avatar");
switch (currentKeyDown) {
case 37: // left arrow key
avatar.setAttribute("player-info", "clip:Walk");
break;
}
});
and in register component if previous clip and new clip are different set a new clip. like this
if (oldData.clip !== this.data.clip) {
this.character.setAttribute('animation-mixer', {clip: this.data.clip, crossFadeDuration: 1});
}
Maybe you can take this code for reference and I have added to glitch. Glitch walking demo
I'm making a Chrome extension that inserts an iframe into the page and applies my own styling to it:
const iframe = document.createElement('iframe');
iframe.style.background = 'white';
iframe.style.position = 'fixed';
iframe.style.width = '300px;
iframe.style.height = '50%';
iframe.style.top = '0';
iframe.style.zIndex = '999';
iframe.frameBorder = 'none';
document.documentElement.appendChild(iframe);
Most of the time this works fine but there are some sites which target iframes with JavaScript and apply some inline CSS which messes up the Layout. https://exchange.adobe.com/creativecloud.html?zpluginId=12557&mv=product&mv2=accc does this when you resize the browser.
Is there any way around this? I tried setting the inline styles as !important but it has on affect.
1. Solution
You could make use of the css property all
In your case it would look like this:
const iframe = document.createElement('iframe');
iframe.style.all = 'unset'; // maybe also add `! important`
// ...
document.documentElement.appendChild(iframe);
2. Solution
If you want to ensure that your style attribute does not get changed. You could get it done with a MutationObserver
const iframe = document.createElement('iframe');
iframe.style.all = 'unset'; // maybe also add `! important`
// ...
document.documentElement.appendChild(iframe);
const observer = new MutationObserver((event) => {
// check if styles differ from your initial ones
// fix them if necessary
});
observer.observe(iframe, {
attributes: true,
attributeFilter: ['style'],
childList: false,
characterData: false
});
It's kind of brute force. But will work for sure.
Have you looked at the sandbox attribute of the iframe? If you set allow-same-origin to false. Then it will cause the iframe to appear like a cross-origin iframe and block the parent page from accessing it.
I am writhing Angular 2+ unit test with TestBed.
Scenario, I want to verify my component, that the color of a pseudo element.
component.ts
label::before {
right: 0;
background-color: red;
}
#Component({
selector: 'app-test',
template: `
<div><label>a label</label></div>
`,
styleUrls: ['./test.component.scss'],
})
export class TestComponent {
}
so when I write unit test, I want to verify the pseudo element background color
beforeEach(() => {
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should set background color', () => {
const ele = fixture.debugElement.query(By.css('label::before')).nativeElement; // error here
// not sure how to use by.css to locate on the pseudo element
expect(ele.backgroundColor).toBe('....');
});
I would suggest writing your test in a different manner.
Fixture is of type ComponentFixture<T> where T is the component you are trying to access. The debugElement property has two properties that you are normally interested In when writing a test componentInstance and nativeElement
ComponentInstance is your component ts file. It's your class declaration in a sense.
NativeElement as the name suggests is the mark-up or your template
I don't think it's possible to do it the way you suggested.
However you could try
const color = window.getComputedStyle(fixture.debugElement.nativeElement.querySelector('label'), ':after').getPropertyValue('background-color');
This will give you a rgb result so for red it would be rgb(255,0,0)
I got this from: How to get pseudo element?
Try this and see if it works. It's not great that we had to access the window element inside of our test but it might solve your issue. Possibly create a better test without having to access the window api i would suggest.
I am using ReactJS with redux.
I using scss.
lets say my path is:
http://localhost:3000/login
I need to add to this page:
html:{ overflow:hidden}
and on other pages i want to remove this attribute.
Anyone have a clue?
You can change the style attribute of the html tag:
class MyPage extends React.Component {
componentWillMount() {
this.htmlTag = document.getElementsByTagName('html')[0];
this.htmlTag.setAttribute('style', 'overflow: hidden');
}
componentWillUnmount() {
this.htmlTag.setAttribute('style', '');
}
...
}
I don't know how is your project architecture, but you can add a class (className) into your HTML tag in differently ways.
If you want, you can also use your redux state.
You check if you are in X page, if it's ok, pass a boolean at true and if it's true, put your css.
I prefer the first solution.
You could just import a className, let's say loginStyle, and make it so:
html: {
overflow: hidden;
}
Then, you just put it as a condition let's say on your header (has to be an element present in every page).
Something like
const isLogin = window.location.pathname === login ? true : false ( <= this is not the real condition, but make it so isLogin equals true is you are on your login page).
<Header className={${className1} ${className2} ${isLogin ? loginStyle : ' '}}/>
And your style will only be applied on your login page. Maybe not the simpliest, but at least this would work :)
I have two routes on my React app: /a and /b.
For /a, I want the body css tag to have a background-color: red;.
For /b, I want the body css tag to have a background-color: blue;.
Both components a and b live in different .JSX files, and both import their own main.scss file which defines their own respective body background-color.
However, since the entire app is compiled into the body tag, there seems to be a conflict, and only one of the body tags is respected for both routes.
<body>
<script src="bundle.js" type="text/javascript"></script>
</body>
The reason I want it on the body tag and not just a container div is that I want the background-color to be visible when I scroll outside the bounds of the page (the bounce effect on Mac and iOS).
What's the proper way to do this?
That's happening because when you import your styles in your component without CSS Modules, the styles are global so your body style is defined two times (you can see all the styles in the <head> tag).
You can fix that by setting the background color in your component componentDidMount() method.
Example
componentDidMount(){
document.body.style.backgroundColor = "red"// Set the style
document.body.className="body-component-a" // Or set the class
}
or, if youre using functional components you can do the same with useEffect...
useEffect(() => {
document.body.className = 'class-name';
}, []);
I agree with what QoP said but, as an add on to that, you should also make sure to use componentWillUnmount to set it back to whatever it normally is outside that component.
for example:
if normally for the whole application text-align is left but for one component you want it to be center, but after the component it needs to return to being left, you will do the following:
componentDidMount() {
document.body.style.textAlign = "center"
}
componentWillUnmount(){
document.body.style.textAlign = "left"
}
Add this code
componentDidMount(){
document.body.style.backgroundColor = "white"
}
Hope to help.