So, i have this code, in react :
const sidebar = document.getElementsByClassName("pro-sidebar");
and, further, i try to change the width value using
function openNav() {
sidebar.style.width = "250px";}
and onClick={closeNav} on a button , but when i try to push the button, it gives me the next error : TypeError: Cannot read property 'style' of undefined.
Why??
We do not manually manipulate the DOM like this in React. Do something like this.
return (
<div style={styles.container} />
)
...
let styles = {
container: {
width: '20px'
}
}
You can use string interpolation on width to programmatically change it with your function.
Related
I am new to the React. Here, I'm trying to override the CSS of a class based on a condition
let customizeColumn = document.querySelector(".main-table-body");
!expandFilter ? customizeColumn.setAttribute("style", `height:calc(100vh - 345px)`) : customizeColumn.setAttribute("style", `height:calc(100vh - 302px)`);
Here, I am managing the state of this variable and I am calling toggleFilter on the button click
const [expandFilter, toggleFilter] = useState(false);
But I don't want to use document.querySelector(".main-table-body") to fetch the class, Is there any other way of doing this. I am using Material-UI too. If that helps
In the render of the main-table-body, check the state to determine what CSS property it should have, eg:
return (
<table
class="main-table-body"
style={{ height: `calc(100vh - ${expandFilter ? 302 : 345}px)` }}
>
// table contents
</table>
);
You can apply style using style attribute.
In the render method do like this
const pixelsToReduce= expandFilter ? 302 : 345
const height=`calc(100vh - pixelsToReduce)`
return (
<table
class="main-table-body"
style={{height:height}}
>
</table>
)
I have a component in React-redux, which has a PagedGrid component (basically a table which renders data row-wise).
<UsersContainer>
<Title>{t('users')}</Title>
<PagedGrid
data-auto-container="user:table"
pageData={user.data}
columns={this.column}
/>
</UsersContainer>
I have created a function for the custom styled component which applies css to the rows of the table inside PagedGrid
const UsersContainer = styled.div`
> table > tbody {
${props => customcss(props)};
}
`;
function customcss({ data = [] }) {
let styles = '';
if (data.length > 0) {
data.forEach((value, index) => {
if (value.mycondition) {
const rowStyle = `& > tr:nth-child(${index + 1}) {
background-color: ${LIGHT_BLUE}
}`;
}
});
}
return css` ${rowStyle} `;
}
Now I want to create a test case using jest to spy on the css of this table and check if the styles are getting applied or not. Can anyone help me on creating a test case for this.
Assuming that you use the #testing-library/react library, you could test your component's style by getting it directly from the html document, and see precisely what style is used for your specific element.
In your example, you can do something like below (assuming that the ${LIGHT_BLUE} value is blue):
import React from 'react';
import { render } from '#testing-library/react';
import UsersContainer from '../UsersContainer';
it('should have the background color set to blue', () => {
const { container, getAllByTestId } = render(
<UsersContainer />
);
// Replace <YOUR_CSS_SELECTOR> by your component's css selector (that can be found in the inspector panel)
let contentDiv = document.querySelector('<YOUR_CSS_SELECTOR>');
let style = window.getComputedStyle(contentDiv[0]);
expect(style.color).toBe('blue');
}
Here, to get the style of your element, I am using the element's CSS Selector. However, it could also work with the element's className, or id directly if it has one, respectively using the methods document.getElementByClassName('YOUR_DIV_CLASS_NAME'), document.getElementId('YOUR_DIV_ID') instead of document.querySelector('<YOUR_CSS_SELECTOR>'). Note that the given name here should be unique, either with the id technique, or the className.
When Gutenberg creates a class, it seems to be of the format
div.wp-block
div.editor-block-list__insertion-point
div.editor-block-list__block-edit
div.editor-block-contextual-toolbar
div
<your actual block html goes here>
I'd like to be able to add a class to that top div.wp-block element so I can properly style my block in the editor. The class is dynamically generated based on an attribute so I can't just use the block name class. Is there a clean way of doing this? I can hack it using javascript DOM, but it gets overwritten quickly enough.
https://wordpress.org/gutenberg/handbook/designers-developers/developers/filters/block-filters/#editor-blocklistblock
const { createHigherOrderComponent } = wp.compose
const withCustomClassName = createHigherOrderComponent((BlockListBlock) => {
return props => {
return <BlockListBlock { ...props } className={ 'my-custom-class' } />
}
}, 'withCustomClassName')
wp.hooks.addFilter('editor.BlockListBlock', 'my-plugin/with-custom-class-name', withCustomClassName)
You can add class in your block edit view by using className that is present in this.props, className will print class in following format wp-blocks-[block_name]
edit( { className } ) { // using destructing from JavaScript ES-6
return <div className={ className }></div>
}
Suggestion
Always try to look for manipulating DOM via React instead of manipulating DOM directly because React manages it's own state and issues can occur by manipulating DOM directly.
Learning React and trying to cheat off this codepen. I do not understand 2 things.
What is the ... before largebox, flex, and other css classes?
return <div style={{...largebox, ...flex}} key={props.id}
What does the $ do in the css url param? Is it jQuery?
`url(${props.photo})
const FormCard = (props) => (
<div>
{
DATA.map((props) => {
return <div style={{...largebox, ...flex}} key={props.id}>
<div style={{...Photo,backgroundImage: `url(${props.photo})`}}></div>
<div>
<Author author={props.author}/>
<Something bio={props.bio}/>
<AdBox adpic={props.adpic} />
<IconBox />
</div>
</div>
})
}
</div>
)
The three dots '...' are called spread operator, see here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
The $ sign is no Jquery but is actually referencing template literals: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
Hopefully, the docs are enough as I currently can't find [the link] to [that tutorial] I remember...
Spread operator:
const styleA = { color: 'red' };
const styleB = { background: 'blue' };
const styleC = { ...styleA, ...styleB };
// styleC = {color: "red", background: "blue"}
String Template:
const user = 'Bob';
const greetings = `Hello ${user}`;
// greetings = 'Hello Bob'
for your first question we call it Spread Operator in a simple description for below line :
style={{...largebox, ...flex}}
this is mean copy all property of largebox and flex object into a new object and assing it to style.or this line means :
style={{...Photo,backgroundImage:"myurl}"}
create a new object for me with all property of Photo object and also add a property with name backgroundImage to it. so if Photo is equal to {name:'1.jpg'} the new object is equal to
{name:'1.jpg',backgroundImage:"myUrl"}
Now for your second question, this is template literal and allow you to write variables or call functions inside a string. think we have not this so we must write it like :
backgroundImage: "url(" + props.photo +")"
so as you see it is something like concating props.photo and other strings.but with template literals we can wrap string with backticks and then write variable or function of javascript between ${} like below
backgroundImage: `url(${props.photo})`
then ${props.photo} replace with its value.
I am using the Grid component and have a cellRenderer. In it I attempt to add a backgroundColor style to the outer div.
customColumnRenderer(props: GridCellProps): React.ReactNode {
...
props.style.backgroundColor = "hotpink";
...
return <div style={props.style}
... </div>;
}
All is good at first, but then I scroll vertically a bit and I get this exception:
Uncaught TypeError: Cannot assign to read only property 'backgroundColor' of object '#<Object>'
When I look in the debugger. props.style looks like a simple Object to me. The doc says
"You can add additional class names or style properties as you would like."
Any thoughts on what I might be doing wrong?
Best workaround I could come up with is to merge in style props from a different object using the spread operator. Something like this:
customColumnRenderer(props: GridCellProps): React.ReactNode {
...
let myStyles = {backgroundColor: "hotpink"};
let styles = {...props.style, ...myStyles};
...
return <div style={styles}
... </div>;
}