I've recently started trying to use react-virtualized, but I've ran into an issue from the get-go. I've been trying to build a very simple grid, at first I loaded my data in and it wasn't working properly, but I've changed it to a simple 4x4 Grid and it's still giving me issues. Right now all 16 cells are being loading in a single column, and I've tried logging the rowIndex and the columnIndex, and those are giving me the correct output.
I'm not sure if I'm doing something wrong when I call the Grid, or if I'm doing something wrong with the cellRenderer, I would really appreciate some help with this. I have parts of my code down below.
_cellRenderer({columnIndex, key, rowIndex, styles}){
return(
<div>
{columnIndex}
</div>);
}
render(){
return(
<div>
<Autosizer>
{({width}) => (
<Grid
cellRenderer={this._cellRenderer}
columnCount={4}
columnWidth={30}
rowCount={4}
rowHeight={30}
width={400}
height={400}
/>
)}
</Autosizer>
</div>
);
}
You aren't using the parameters passed to your renderer. For example, style and key are both passed for a reason and you must use them. (The documentation should make this pretty clear.)
Put another way:
// Wrong:
function cellRenderer ({ columnIndex, key, rowIndex, style }) {
return (
<div>
{columnIndex}
</div>
)
}
// Right:
function cellRenderer ({ columnIndex, key, rowIndex, style }) {
return (
<div
key={key}
style={style}
>
{columnIndex}
</div>
)
}
Also, in case you didn't notice, the parameter is style and not styles like your code snippet shows.
Related
I have the following which works fine where I am using in line style to decide the percentage values based on a boolean value.
Is there a way I could prevent using inline styling and instead pass this styling to my scss file and still be able to perform this logic more elegantly?
Working copy with inline styling.
const MyPage = ({isSmall}) => {
return (
<div>
<div style={{flex: `0 0 ${isSmall ? '50%' : '33%'}`}}>
hello
</div>
</div>
);
};
export default MyPage;
Looking to be able to move my css to my scss file and use that as a className instead but still be able to toggle the percentage value based on the boolean isSmall prop value.
Move it to scss file.
.flexer {
flex: '0 0 33%' // some way to make the 33% be dynamic and not hard code like this to be able to switch its value between 50% and 33%
}
Then use this flexer class instead of inline css.
Is this possible? Or any better elegant way to achieve this instead of inline?
You can set boolean state and change class name depends on this state inside the className then you can modifiy it in css
const MyPage = ({isSmall}) => {
const [isSmall,setIsSmall] = useState(false);
return (
<div>
<div className={isBigClass `${isSmall} ? "isSmallClass" : ""}`} >
hello
</div>
</div>
);
};
export default MyPage;
I am working to develop a custom block that allows the user to add tabs, and then populate each tab with as much content as desired using other gutenberg blocks. Its my understanding that there can only be a single instance of InnerBlocks in the edit / save function - even though that seems at first like how you would implement the functionality I am looking for (a single instance of InnerBlocks.Content for each tab.
So far, I have been unable to find a good resource on the high level methodology for implementing tabs or columns as a custom gutenberg block. I have reviewed some of the wordpress block library column code, however I find it to be pretty complex and abstract for beginner development of custom blocks.
I am hoping to receive guidance from a high level on how one would achieve the functionality I am looking for. Below I have included my very simple tabs block code for reference.
const { __ } = window.wp.i18n;
const { registerBlockType } = window.wp.blocks;
const { InnerBlocks, RichText } = window.wp.blockEditor;
registerBlockType('myplugin/tabs', {
title: __('Tabs', 'myplugin'),
category: 'widgets',
attributes: {
tabs: {
type: 'array',
default: []
}
},
edit: function ({
className,
attributes,
setAttributes,
}) {
let { tabs } = attributes;
return (
<div className={className}>
<button onClick={() => setAttributes({ tabs: [...tabs, { title: 'New Tab' }] })}>Add a tab</button>
{tabs.map((tab, i) => {
return (
<div key={i}>
<div>
<RichText
tagName="div"
value={tab.title}
onChange={(value) => {
tabs[i].title = value;
setAttributes({ tabs })
}}
/>
</div>
<div>
<InnerBlocks
allowedBlocks={ ALLOWED_BLOCKS }
/>
</div>
</div>
)
})}
</div>
)
},
save: function ({
attributes,
}) {
const { tabs } = attributes;
return (
<div>
{tabs.map((tab, i) => {
return (
<div key={i}>
<div>
{tab.title}
</div>
<div>
<InnerBlocks.Content />
</div>
</div>
)
})}
</div>
)
}
});
The pattern for creating blocks with multiple nested children is as follows. First define 2 block types, a parent and a child. Gutenberg core Block Columns is an example of this, there is "Columns Block" as the parent and then there is "Column Block" as the child block.
The use of the parent and child block enable us as developers to work around the restriction of only 1 InnerBlock region per block. It enables the structure using tabs as an example where we have:
/tabs-parent-block
/tab-child-block-1
/tab-child-block-2
/tab-child-block-3
These child blocks could still be within 1 InnerBlocks section which enables the user to add more child blocks. You can restrict the block types for child block to your custom tab child block using the <InnerBlocks allowedBlockType={ ALLOWED_BLOCK_TYPES } />.
What about a situation where putting all the child blocks in one area isn't practical? That is something I'm still experimenting with myself. It doesn't seem to matter for things like tabs because the parent/child approach should work. But what if it doesn't and you really need to have a parent block that has entirely different regions like for a page layout?
The reference shared in an earlier answer is relevant, this script registers 2 blocks which work together in the parent/child block pattern: https://github.com/Ultimate-Blocks/Ultimate-Blocks/blob/master/src/blocks/tabbed-content/components/tab.js
Notice that the first block registered is a singular tab (child block) ub/tab, the second block registered is the parent block ub/tab-block. In the parent block the save() function saves only the child tabs using <InnerBlocks.Content />.
The way to do this is to define another block which then to include in the parent block.
You can check out this plugin: https://github.com/Ultimate-Blocks/Ultimate-Blocks/tree/master/src/blocks/tabbed-content
I want to display a specific number of components around a component. How can I do that? :)
With this implementation, I draw 8 Patrat component
{Array.from(Array(8)).map((item, index) =>
(<Patrat key={index}/>)
)}
I want to display these 8 Patrat around a circle which is also a component.
After Understanding the issue and what you want here is the final solution
You can also create function which can dynamically create position and pass it to the Child components
Here is complete code resource link (Click Here)
Also your can experiment with some comment line in code link given above
You could create a recursive loop where you create a new Patrat component with the recursive call as children to it.
Example
function Patrat({ children }) {
return (
<div
style={{
paddingLeft: 10,
backgroundColor: "#" + Math.floor(Math.random() * 16777215).toString(16)
}}
>
{children}
</div>
);
}
function App() {
const content = (function patratLoop(num) {
if (num === 0) {
return <div> Foo </div>;
}
return <Patrat>{patratLoop(--num)}</Patrat>;
})(8);
return content;
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
You could make the circle responsible for positioning the elements, then have Patrats as children of circle (Circle > div.circle_element_position > Patrat) or if Patrats will change depending on the parent component, you could use same logic but use renderProps for Patrats (Circle > div.circle_element_position > props.renderPatrat(index))
It would look more or less like this:
function Partat() {
return <div>1</div>
}
function calculatePositions(numberOfPatrats) {
//your implementation
}
function Circle ({numberOfPatrats}) {
let positions = calculatePositions(numberOfPatrats);
return <div className="circle">
{positions.map(
(position, index) => <div style={position} key={index}><Partat /></div>
)}
</div>
}
To place Parats on the positions you want you just need to implement calculatePositions, which will be similar to what you had in your jsfiddle example.
I like how the columns block works because it supports nesting. What I'm trying to do is similar to making the column block support 1 column (which you can force it to do, but it doesn't size correctly. This way, the entire block of multiple blocks and block types can be saved as a single reusable block instance.
Is this an instance where I need to start working on my own custom block type? Or will this be supported at some point?
What you need is InnerBlock. You can basically, group couple of blocks into a single custom block.
import { registerBlockType } from '#wordpress/blocks';
import { InnerBlocks } from '#wordpress/editor';
registerBlockType( 'my-plugin/my-block', {
// ...
edit( { className } ) {
return (
<div className={ className }>
<InnerBlocks />
</div>
);
},
save() {
return (
<div>
<InnerBlocks.Content />
</div>
);
}
} );
Btw, this is the main focus of Gutenberg Phase 2 development. And, Gutenberg will slowly take over into template building process.
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.