creating a list with react-dropzone - reactjs

I'm trying to create a gallery using react-dropzone. I am successfully adding images but instead of creating an array, as I thought I was doing by following their github, it is simply loading an image and replacing it with the new one when I drag another image. The expected result is to add the image next to the one I already dragged in it.
I am specifying an empty array called files: [], that I imagine will collect the images.
The dropzone element in my class looks like this:
let dropzoneRef;
<Dropzone
ref={
(node) => {
dropzoneRef = node;
}
}
onDrop={this.onDrop.bind(this)}>
<p>Drop files here.</p>
</Dropzone>
<RaisedButton
label="Upload File"
primary={false}
className="primary-button"
onClick={() => { dropzoneRef.open(); }}
/>
<ul>
{
this.state.files.map(f =>
<li key={f.preview}>
<img className="dropped-image" src={f.preview} alt=""/>
</li>,
)
}
</ul>
I added the working code to a WebpackBin for you to inspect
Their github docs are here
This is my goal screen. I haven't worked out the second part which is clicking on any single thumbnail added and showing it in full size. So don't worry about that part. I just need to be able to collect a list and add as many as I want. Here is a screenshot of the expected result. (I apologize for the kindergarten writing)
Thank you in advance

All you need to do is update your onDrop function as follows
onDrop(uploadedFile) {
this.setState({
files: this.state.files.concat(uploadedFile),
});
}
This is because you want to add the new file to this.state.files array.
See this updated WebpackBin.

Related

How to prevent react-quill to insert a new line before list when re-loading content?

Using react-quill, I write a list within text, store the content into external storage, reload the content into quill: a new <br> is inserted before the list, and it happens on each reload.
Any idea what is happening, and how to prevent it?
I prepared a minimal sandbox to show the issue: https://codesandbox.io/s/reverent-cookies-m5h3x
The steps to reproduce:
write a line, followed by a bullet list
click save to store the content to external storage
click clear to remove all content from the editor
click load to put the content from external storage to the editor
BOOM! A new <br> is inserted on each save-clear-load cycle
Found this answer by mhdhamouday in Quill GitHub Issues. This works for me.
var quill = new Quill('.quill', {
theme: 'snow',
modules: {
toolbar : [...]
clipboard: {
matchVisual: false
}
}
});
https://github.com/quilljs/quill/issues/2905#issuecomment-683128521 solution works very well. If you are using react component, this can be an alternative.
<ReactQuill
theme="snow"
value={block.note}
onChange={(value) => onEditorStateChange(value, block)}
modules={{
clipboard: {
matchVisual: false
}
}}
/>

Add image to the DOM dynamically in react

I have a socket connection that updates a binary data.
By click I would like to update an image src , the images are created blank with empty src and with id , but I did not found how do I doing something like :
$('imageId').src = 'new src' like in Jquery
I have array of images so I cant define per each image this.ref or something
my socket code: // here I want to update the specific image
divSocket.on('data', (data) => {
var bytes = new Uint8Array(data);
this.setState({
imageSrc : someBufferFunction(bytes)
})
});
my render code
{ this.props.list.map((item,i) =>(
<div className="img">
<img id={`cam${i}`} src={`data:image/jpeg;base64,${this.state.imageSrc}`} />
</div>
))}
the problem is that this.state.ImageSrc will update all images and will show socket data (video) in all the images
I can create an image with specific id in loop but how do I update specific image via props/state
You're using an array to display images ... from props ... this.props.list
This list should contain data for each image ... but item argument isn't used in .map rendering.
I need to make a placeholder
Assuming that props.list doesn't contain any data ... used as loop counter ... renders placeholders only ... you need:
an array of src in local state (this.state.sources = [];)
you should render images using key prop:
{ this.props.list.map((item,i) => (
<div className="img" key={`cam${i}`} >
<img id={`cam${i}`} src={this.state.sources[i]} />
</div>
))}
you can use placeholder image for empty 'cells'
<img id={`cam${i}`} src={this.state.sources[i] ? this.state.sources[i] : "url_somePlaceholder.jpg"} />
New image from socket needs to update an array element using index - not common one for all images in this.state.sources - see React: how to update state.item[1] in state using setState? for inspirations.
If assumed earlier props.list contains image sources at start - copy values into state (in componentDidMount, componentDidUpdate or static getDerivedStateFromProps )

angular: asynchronously fill an array

I have an array of elements, a big one, rendered in a dropdown with *ngFor. Whenever I click to open the dropdown, the UI is blocked for a certain amount of time. Finally the dropdown opens and the items are all there.
It's not a big problem but I am trying to make the dropdown to instantly open on click, and the list to be filled and rendered asynchronously.
The original list is synchronously available, in a variable (it's not given from async call to server).
I think I should create a mirror array, starting from an empty, and write an asynchronous function to push elements from the original list to the mirror one.
What's a way to do something like that? I can't grab how to use observables for doing so.
This is my simplified setup
Component
source = [...]; // a thousand of objects
mirror = []; // progressively filled with source elements
async onDropdownOpen(open: boolean) {
if (open) {
// async fill of mirror
} else {
// empty mirror to boost next time dropdown opening
mirror = [];
}
}
Template (I am using ngBootstrap)
<div
ngbDropdown
#dd="ngbDropdown"
(openChange)="onDropdownOpen($event)">
<button class="btn btn-outline-primary" id="dropdownBasic1" ngbDropdownToggle>Toggle dropdown</button>
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
<div *ngFor="let el of mirror">
... async el rendering ...
</div>
</div>
</div>
It looks like you could use the Angular CDK Virtual Scroll directive.
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
<div *cdkVirtualFor="let el of mirror">
... async el rendering ...
</div>
</div>
https://material.angular.io/cdk/scrolling/overview

How to use a method in the Main component on another

I am trying to save notes into localStorage (or in this case localforage). I have a simple text area with a button called "save." The save button is located in another file indicated below.
I used an example found here to try to set the items.
This is the code I wrote:
SaveMessage() {
var message = <Notepad></Notepad>;
reactLocalforage
.SetItem("Message", message, function(message) {
console.log(message);
})
.catch(function(err) {
console.log(err);
});
}
The var message is something I'm not too sure of either. Notepad is another component with the code which contains the text area and buttons:
<div className="button-container">
<button
className="save-button"
onClick={() => {
props.onSaveMessage(saveMessage);
}}
>
Save
</button>
<button className="remove-button">Show all</button>
</div>
The area where it says onClick I was hoping there would be a way to use the SaveMessage method with localforage initially I tried creating it as a prop (from a tutorial) so in the main method I'd have:
render() {
return (
<div>
<Notepad onSaveMessage={this.SaveMessage}></Notepad>
</div>
);
}
and then on the Notepad component:
<button
className="save-button"
onClick={() => {
props.onSaveMessage();
}}
>
Save
</button>
When I click the save button on my application I am hoping something will be set within the local-storage on the browser, but I get an exception:
TypeError: Cannot call a class as a function
The error occurs when I set item on the save message code above and when I try to call it as a prop onSaveMessage(saveMessage).
You haven't added enough code to be able to fix your exact issue, but I can help you understand how you should proceed to fix it. In React when you want to share information between components, you need to lift that data into a parent component, and then share it through props. If your component tree is profound, then this task can get tedious. So several libraries have been developed to manage your app's state.
I suggest you start by reading "Lifting State Up" from the React docs page. To help you apply these concepts to your current situation, I've created a CodeSandbox in which I try to replicate your situation. You can find it here.
Once you understand the need to "lift" your state, and how you can share both data and actions through props you can migrate to state handler tool. Some of them are:
React Context
Redux
MobX
There are much more. It is not an extensive list, nor the best, just the ones I have used and can vouch that they can help you.
I hope this helps.

React create an thumbnail for each object dynamically

Hello guys im trying to create an div for each thumbnail in my personas ={[]} it should use this.props.personas.map something like this
{this.props.personas.map(thumbnail => {
return <div><img src={this.props.thumbnail /}></div>
})}
i already tried this but failed here is my bin. Bin
any suggestions? what im doing wrong
I am assuming the src for the images is in the personas array (i know you call it thumbnail, but for consistency sake let's use persona instead)? If so, you should use persona instead of this.props.thumbnail
{
this.props.personas.map((persona, i) => {
return <div key={i}><img src={persona.thumbnail} /></div>
})
}
The answer aside, it is good practice to use key prop on dynamically generated components. Read about keys here: https://facebook.github.io/react/docs/lists-and-keys.html#keys

Resources