bootstrap react JS global - react-bootstrap

I am new to react JS and stuck in a very basic issue. I am using Bootstrap 'Offcanvas' component but the problem is that the button to toggle it is header while the menu itself is in different file. I dont know how to define global const to manage it
CONST
const [showSidebar, setShowSidebar] = useState(false);
const handleSidebarClose = () => setShowSidebar(false);
const handleSidebarShow = () => setShowSidebar(true);
HEADER.JS
<Button variant="primary" onClick={handleSidebarShow}>Show Meny</Button>
SIDEBAR.JS
<Offcanvas show={showSidebar} onHide={handleSidebarClose}>
<Offcanvas.Body>
Some text as placeholder. In real life you can have the elements you
have chosen. Like, text, images, lists, etc.
</Offcanvas.Body>
</Offcanvas>
Where should i place these consts and make them global?

You have to put the state, that is needed by several other components above them. This is called "lifting the state". Then hand over the state or/and your functions to the components below via props. For example:
Put state in App.js
Import Header and Sidebar in App.js
Give Header and Sidebar appropriate properties showSidebar, handleSidebarClose , handleSidebarShow
Please look into following sandbox for a working example: https://codesandbox.io/s/vigilant-mopsa-5f6us9

Related

How to stop React Hooks component rerender on SOME state changes?

I have the following code:
const PlayArea = () => {
const [foo, setFoo] = useState('foo')
const [bar, setBar] = useState('bar')
return <div>{bar}</div>
}
In my project, whenever I use setFoo, the whole component re-renders, and I'm trying to prevent that. I only want the component to re-rerender when bar changes.
Is there anyway that I can keep the component from changing from using setFoo ?
Is there anyway that I can keep the component from changing from using
setFoo ?
No. By design state variables work such that when you change them that component will rerender.
But If you don't want to rerender your component when you update that variable then why are you using a state variable? Use useRef
Keep in mind that useRef doesn’t notify you when its content changes.
Mutating the .current property doesn’t cause a re-render.

Reduce Vue Bundle Size, and increase Vue Performance

I have big issue on vue performance on initial load time and size, picture below shown the vue-plotly is the main factor. However, I didn't use the vue-plotly package but my vue-pivottable(Pivot Table Component) using it.
I had try dynamic load on my route and view page.
eg: const PivotTable = () => import('#/components/PivotTable')
but result are still the same.
How could I prevent this package from initial load. Thanks in advance.
You can use code splitting and lazy loading feature of webpack.
May be as easy as
const PivotTable = () => import(/* webpackChunkName: "pivot-table" */ '#/components/PivotTable')
Though it may get a bit more complicated, since you may need to handle the fact PivotTable is loaded asynchronously.
There's couple ways to do that, the simplest is to bundle it with the component that uses it.
To do that you would import the component in a parent with webchunk name that matches the Pivot table
SomeFooParent.vue
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
Foo.vue
const PivotTable = () => import(/* webpackChunkName: "group-foo" */ '#/components/PivotTable')
This way the entire component is in the same bundle, and as long as the component is not present on the initial load, it will not load on start and the entire component, with the pivotTable dependency, will load on demand.
Alternatively, you could dive into handling the PivotTable as unresolved promise and await loading before using it. See example how webpack recommends handling lazy loading a chunk on button click.

Making focus works inside a CK Editor 5 createUIElement

So I've a custom widget which renders a custom component.
conversion.for('editingDowncast').elementToElement({
model: 'modelName',
view: (modelElement, viewWriter) => {
const modelName = modelElement.getAttribute('modelName');
const modelNameView = viewWriter.createContainerElement('span', {
class: 'modelName',
'data-modelName': modelName,
});
const reactWrapper = viewWriter.createUIElement(
'span',
{
class: 'modelName__react-wrapper',
},
function (this, domDocument) {
const domElement = this.toDomElement(domDocument);
rendermodelName(modelName, domElement);
return domElement;
},
);
viewWriter.insert(
viewWriter.createPositionAt(modelNameView, 0),
reactWrapper,
);
return toWidgetEditable(modelNameView, viewWriter);
},
});
Where rendermodelName will give back a React component with a simple input box as
return (
<div>
<input type="text" />
</div>
);
https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/frameworks/react.html.
But the problem is, whenever I tried to add some content inside the input, the focus is lost from the field and automatically moved to the surrounding editor. What am I missing. Tried creating a focushandler and adding the modelNameView to it.
Should I go with the new createRawElement? My current CK5 is 20.0.0 So I don't want any breaking changes coming now.
EDIT:
I researched a little bit more. seems like createRawElement may not work here. I think this doesn't have a simple solution. I tried with allowContentOf: '$block' which also not letting me focus. But these values are explicitly for normal CK widget, not for a react component.
I had the same issue and solved it by adding this tag to the parent div that wraps my Vue component.
https://ckeditor.com/docs/ckeditor5/latest/framework/guides/deep-dive/ui/widget-internals.html#exclude-dom-events-from-default-handlers
Adding from CKE Docs:
Sometimes it can be useful to prevent processing of events by default handlers, for example using React component inside an UIElement in the widget where, by default, widget itself wants to control everything. To make it possible the only thing to do is to add a data-cke-ignore-events attribute to an element or to its ancestor and then all events triggered by any of children from that element will be ignored in default handlers.
Let’s see it in an short example:
<div data-cke-ignore-events="true">
<button>Click!</button>
</div>
In the above template events dispatched from the button, which is placed inside containing data-cke-ignore-events attribute, will be ignored by default event handlers.
I faced the similar issue.
CKEditor will takes all the events on React component which you hosted on Widget.
The work around is to stop propagation of events to CKEditor which are fired from your DOM element(domElement) where your React component hosted.
Here is the sample code:
https://github.com/ckeditor/ckeditor5-core/compare/proto/input-widget#diff-44ca1561ce575490eac0d660407d5144R239
You should stop all required events. Also you can't paste any content inside the input field of React component. That will also listened by clipboardInput event of CKEditor.

React Admin page not rendering correctly

I am new to UI coding and started using react-admin for putting some simple pages. Everything went well and we are able to host pages correctly. But we have noticed random issues where the background image is filling up the entire screen or sometimes the whole page gets reduced to the hamburger menu. I have disabled the registerServiceWorker to stop having my pages in cache. Not sure if this is causing the weird UI behavior.
I don't know why you get those issues, the description is way too generic and it seems you don't have any idea what the problem can be, probably due to being new to the area. Either way the kind of problem you appear to have is probably related to CSS which is a way give style to your page. But React Admin doesn't use CSS directly, you can use it that way, but for more dynamic way to style the page the Material-ui library uses a thing called JSS to apply the styles.
There are many libraries that are being used together in order to produce React Admin, you should have an understanding of the most important ones in order to do something fancy. My advice to you since you are new, and you pretend to use React Admin, first use what React Admin offers and when you feel comfortable using that components and have a general grasp how the framework works, after that start implementing your own components that don't have a direct relation to React Admin but use some of the same libraries of React Admin.
Also check if you are creating a React Admin app using the <Admin> component or are embedding React Admin in another app since the second is more probable to produce bugs.
After some debugging, I think i figured out the cause of this issue. I had a custom button to duplicate a row (basically post a create and route to edit page on the new id). For some reason, the rendering of that button seems to have caused this issue inconsistently. The actual button works fine but causes this inconsistent behavior. Below is the code for that button. Is there any issue with the below?:
export default class DuplicateButton extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = ({ redirect: false });
var redirectPath = '';
}
handleClick = (props) => {
var
{
push, record, resourceName
} = this.props;
let tempRecord = record;
var result = '';
console.log(this.props);
var p = restDataProvider(CREATE, this.props.resource + "/" + tempRecord.id, { data: tempRecord }).then(resp => {
result = resp.data;
let routePath = '/' + this.props.resource + '/' + result.id;
console.log(routePath);
this.redirectPath = routePath;
this.setState({ redirect: true });
return result;
});
}
render() {
if (this.state.redirect) {
console.log('Redirect to Edit page');
return <Redirect push to={this.redirectPath} />;
}
return <Button variant="flat" color="primary" label="Duplicate Entry" onClick={this.handleClick}><DuplicateIcon /></Button>;
}
}

Global dialog implementation with vue

I am need a reusable, global dialog/modal component in my vue application. I need to be able to call it from any component and update its header text, body text and callback function once the dismiss button is pressed on the modal. I have tried importing a custom made dialog component into each component where I plan to use it and I have tried creating a global dialog where the values would be set using a mutable values in a modals vuex modal. This latter did not work because vuex will not store functions as values. I am new to vue and am not too sure how to go about this and absolutely any advice on a good way to go about it would help tremendously.
I did something like that before. The main ingredient is the handling of events through the $root because you can't relay in this scenario on the normal component communication.
// In your Global Modal
<script>
export default {
name: 'GlobalModal',
mounted () {
this.$root.$on('callGlobalModal', () => {
this.dialog = true
})
},
data: () => ({
dialog: false,
}),
}
</script>
Then call it frome anywhere using this.$root.$emit('callGlobalModal')

Resources