Code Bug Fix: react vertical carousel with react-image-gallery

Original Source Link

I am using react-image-gallery

how to auto-play images vertically?

the problem is to view them vertically like below

vertical slider

import ImageGallery from 'react-image-gallery';
function HomePage(props) {
   const imagesFromFolder = [
    {
        original: 'https://picsum.photos/id/1015/1000/600/',
        thumbnail: 'https://picsum.photos/id/1015/250/150/',
    }];

 return (

    <div className="home-page"> <div className="sidenav" style={{ width: "450px" }}>
            <ImageGallery disableThumbnailScroll={false} showThumbnails={true} showNav={false}
                isRTL={false} autoPlay={true} thumbnailPosition="left"
                stopPropagation={true}
                items={imagesFromFolder} />
/>
 </div >
);
 }
export default HomePage;

update
Is there is a way to do that?

Tagged : /

Code Bug Fix: React: Memory Leak in Array.Map Function

Original Source Link

I am new to react and maybe this is trivial. I have an issue I can’t seem to solve and that keeps popping up. Whenever, I render using the map function for arrays in javascript, and the items I am rendering don’t appear at once, but one by one or in chunks that depend on some changing variable,i.e. an index for a carousel or an accordion. I always get this warning:

Warning: Can’t perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

I have read about useEffect cleanups in the react docs and from this excellent source: React Hook – Clean Up useEffect. However, I found that none of the solutions are applicable for my use case. Does anyone have a solution? Below is the code for the accordion:

//* EXTERNAL IMPORTS
import React, { useState } from 'react'
import styled from 'styled-components'
import { FixedSizeList as List } from 'react-window'
import AutoSizer from 'react-virtualized-auto-sizer'

//* LOCAL IMPORTS
import RowComponent from './RowMenuItem'
import Accordion from '../components/Accordion'
import { ACCORDION_HEIGHT } from '../utils/constants'

//* STYLES
const Container = styled.div`
  width: 100%;
  height: 99%;
  overflow-y: scroll;
`

/**
 * * The Menu displays the products of a particular category
 * * The display is powered by react-window. 
 * * React-window is unnecessary for small lists and fast devices,
 * * however, for devices with low RAM, it can come in handy. 
 */

const Menu = ({ products }) => {

  /** 
   * * Each accordion has an accordionIndex, if that index matches with the 
   * * state index, then that accordion is displayed
  */
  const [index, setIndex] = useState(-1);

  //* Getting all unique subcategories in this category
  const subCategories = [...new Set(products.map(p => p.subCategory.name))]


  return <Container>
    {
      subCategories.map((subCat, i) => {
        /**  
         * * This function returns a list of all Accordions, each accordion has products
         * * belongin to a unique subcategory
         */

        const children = (
          <AutoSizer>
            {({ width }) => (
              <List
                height={ACCORDION_HEIGHT}
                itemCount={products.filter(p => p.subCategory.name === subCat).length}
                itemSize={40}
                width={width}
                itemData={{ products: products.filter(p => p.subCategory.name === subCat) }}
              >
                {RowComponent}
              </List>
            )}
          </AutoSizer>)

        return (
          <Accordion
            key={i}
            category={products[0].category}
            subcategory={subCat}
            open={index === i}
            accordionIndex={i}
            components={children}
            setIndex={setIndex}
          />)

      })
    }
  </Container>
}

export default Menu
<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>

The warning is at the line I return the Accordion component.

Similarly, For the slider, I have a custom hook which looks like this:

import React from 'react'
import styled from "styled-components"
import { animated } from "react-spring";

const BackImage = animated(styled.img`
filter: blur(10px);
position: fixed;
z-index: 0;
`)

const FrontImage = animated(styled.img`
position: fixed;
z-index: 1;
`)

export default function useAnimatedImages(myImages, isFront) {
  const front = myImages.map(im => ({ style }) => (
    <FrontImage
      src={im.src}
      width={im.recommendedWidth}
      height={im.recommendedHeight}
      style={style}
    />
  ))

  const back = myImages.map(im => ({ style }) => (
    <BackImage
      src={im.src}
      width={1000}
      style={style}
    />
  ))

  return isFront ? front : back

};

The warning is in tha map function at the line where I return the FrontImage and the BackImage.

Tagged : / / / /

Code Bug Fix: how to get a button element to change an h1 element in Reactjs?

Original Source Link

I am trying to make react app where I have a button that causes an h1 element on my screen to display a joke generated from an npm package. I can tell npm package has installed successfully (by checking my console.log element), but i cant seem to get the button to change the existing h1. I receive no error message when the code compiles.

import React from 'react'

var oneLinerJoke = require('one-liner-joke');
var getRandomJoke = oneLinerJoke.getRandomJoke();
console.log(getRandomJoke)



function getJoke(){
  let h1 = document.querySelector('h1');
let changedH1 = document.getElementById('jokeline').innerHTML={getRandomJoke};
  return changedH1;
}

const Template = (props) => {
  return(
    <div>
<h1 id='jokeLine'>Click the button to read a joke</h1>
<button onclick= 'getJoke()'>Get ready to laff</button>

    </div>
   )

 }

export default Template

Use React state to save the joke and display it to screen. Don’t directly manipulate DOM if not really required. I have updated the code with state you can check this by running at your end.

I have use react hooks to use state functionality in React’s functional component.

import React, {useState} from 'react'
import oneLinerJoke from 'one-liner-joke';


const Template = (props) => {
 const [joke, setJoke] = useState(null);

 const getJoke = () => {
    setJoke(oneLinerJoke.getRandomJoke());
 }

  return(
    <div>
<h1 id='jokeLine'>{joke ? joke : 'Click the button to read a joke'}</h1>
<button onclick= 'getJoke()'>Get ready to laff</button>

    </div>
   )

 }

export default Template
Tagged : / / /

Code Bug Fix: Getting unexpected error with flow in shared module of monorepo using next js

Original Source Link

I have a simple project with monorepo setup. When i try to use/import a shared module inside web next js project am getting the below error

image

Next.js by default won’t compile / transpile modules inside node_modules / out-side of the main folder, therefore you get exception on flow syntax at runtime.

I’m using next-transpile-modules in order to transpile specific modules.

// next.config.js

const withTM = require('next-transpile-modules')(['shared-ui', 'other-shared-lib']);

modules.exports = withTM({
  ...regular next config
});

Tagged : / / / /

Code Bug Fix: Django React: API HTML Response not rendering no the browser

Original Source Link

As an exercise, I was trying to render and HTML Response trying to use Django Rest Framework Renderers.
I have a React frontend that sends a post request to the API

request in a react component

axios.get('/api/upload_photo', config).then(res => res.render())

router

router.register("api/upload_photo", UploadPhotoViewSet, "upload_photo")

API

class UploadPhotoViewSet(viewsets.ViewSet):
    parser_class = (FileUploadParser,)
    renderer_classes = [TemplateHTMLRenderer]

    def list(self, request, format=None):

        return Response({}, template_name='api/test.html')

template.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>HEEEEEY it worked</h1>
</body>
</html>

The problem is I get the response with the Html page but it’s just as response and the Html doesn’t render on the browser

Tagged : / /

Code Bug Fix: React router is stacking routes

Original Source Link

I’m trying again:

I’m using props.history.push(‘/something’) from a route ‘/test’

but then I’m redirected to ‘/test/something’ instead of ‘/something’ how can I make it happen?

my example cant work with <Route> <Redirect> <Route> because I’m passing props with my router, for example ‘/something/:id’ any ideas?

EDIT:

  <Route
            exact
            path="/search/:id"
            render={(props) => <SearchResults />}
          />

when I use onclick function like so:

const onSubmit = () => {
    props.history.push(`search/${id}`)
  }

I get pushed to search/search/:id instead of search/:id ( I have the search button always present in all my components) any ideas?

Since you do not add a prefix / to your history.push method, it redirects you to the route relative to the current route i.e if your current route /search, props.history.push(/search/${id}) will take you to /search/search/:id

Adding a prefix / will fix your issue. since it tells the history to add an absolute route

const onSubmit = () => {
    props.history.push(`/search/${id}`)
  }

Tagged : /

Code Bug Fix: ReactJS: how to make two backend requests at once?

Original Source Link

Is it possible to make two backend requests at once from react?

The code below is the first backend call. The post request gets send to the backend and then I would like to do another request. Is it possible at all? Or do I have to wait for the backend response until the next request could be made?
What I basically want is to get information about how many files have been uploaded. The upload could take 3 minutes and the user right now only sees a loading icon. I want to additionally add a text like "50 of 800 Literatures uploaded" and 10 seconds later "100 of 800 litereratures uploaded".

This is basically my code :

class ProjectLiterature extends Component {
  constructor(props) {
    super(props);
    this.state = {

      isLoading:"false",
}
}
  addLiterature(data, project_name) {

    this.setState({ isLoading:true }, () => {
      axios.post("http://127.0.0.1:5000/sendLiterature", data })
        .then(res => {

          this.setState({ isLoading: false })
        })
    })
  }

If both requests do not depend on each other, you can make use of JavaScript’s Promise.all() for the above purpose.

const request1 = axios.get('http://127.0.0.1:5000/sendLiterature');
const request2 = axios.get(url2);

Promise.all([request1,request2]).then([res1, res2] => {
  // handle the rest
}).catch((error) =>  {
  console.error(error);
  // carry out error handling
});

If the second request relies on the response of the first request, you will have to wait for the first request to be completed as both requests have to be carried out in sequence.

const res = await axios.get('http://127.0.0.1:5000/sendLiterature');
// carry out the rest

You can see axios docs for this purpose, they support multiple requests out of box.
You can use Promise.all instead of axios.all as well but if one of requests fails then you won’t be able to get response of successful calls. If you want get successful response even though some calls fails then you can use Promise.allSettled.

Tagged : / / / /

Code Bug Fix: Is there a way for a React Component to be notified when the element it is attached to is deleted outside of React

Original Source Link

Our application consists of lots of legacy code written using jQuery and some newer React components.
We have mostly been able to handle separating concerns between the two, most of our code is one or the other – but occasionally we have React Components within JQuery Components.

In most cases:
JQuery creates a Div, the Div Element is passed to a ReactDOM.render and control for that div is controlled by react.
Then before JQuery destroys the Div it will call ReactDOM.unmountComponentAtNode to do the tear down.

However we have some JQuery code that is being removed in a way that is not trivial to detect that some of it is actually React, creating a component memory leak.

The correct fix for us it to solve the tear down, so that the unMounts are always called correctly, but there are engineering risks in this as the legacy code is not the cleanest and the risk of introduction of new bugs is high.

My question is whether there is a way that React Components can spot that they have become orphaned. ComponentWillUnmount is not the answer (as it does not get called in this scenario).

You could use a mutation observer on the component’s parent, but I’d be surprised if it were really necessary.

Basically, you’d:

  • Use a ref on the top-level element returned by your component in render.
  • In componentDidMount, use current from the ref to find the parentNode and set up a mutation observer on it, watching for childList changes.
  • In the observer callback, look for a mutation record where the ref’s current node in the list of removed nodes.
    • If so, do any cleanup that you have to do.

Live Example:

class Example extends React.Component {
    constructor(props) {
        super(props);
        this.ref = React.createRef(null);
        this.cleanedUp = false;
    }
    
    componentDidMount() {
        this.cleanedUp = false;
        // assert(this.ref.current !== null);
        if (this.observer) {
            this.observer.disconnect();
        }
        this.observer = new MutationObserver(records => {
            if (this.cleanedUp) {
                return;
            }
            for (const record of records) {
                for (const node of record.removedNodes) {
                    if (node === this.ref.current) {
                        this.cleanup();
                        return;
                    }
                }
            }
        });
        this.observer.observe(this.ref.current.parentElement, {
            childList: true,
            subtree: true
        });
    }
    
    componentWillUnmount() {
        this.cleanup();
    }

    cleanup() {
        console.log("Clean up here");
        this.observer.disconnect();
        this.observer = null;
        this.cleanedUp = true;
    }
    
    render() {
        return <div ref={this.ref}>This is the component's top level element</div>;
    }
}

const root = document.getElementById("root");
ReactDOM.render(<Example/>, root);

// Outside React...
setTimeout(() => {
    root.innerHTML = ""; // Bludgeon its contents
}, 1000);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

You might have to watch from further up in the document tree than just the component’s immediate parent, but that’s the general idea…


Note: Using for-of on the removedNodes as I have above relies on the browser making NodeList iterable. Modern browsers do, but slightly older ones may not. My answer here talks about how to make them iterable (assuming the iteration protocol is supported by the browser’s JavaScript engine), or you might use forEach instead (also discussed there).

Tagged : /

Code Bug Fix: React doesn’t rendering list [duplicate]

Original Source Link

 <List style={{ backgroundColor: '#fff' }} dataArray={this.state.basket}
          renderRow={(item) =>
            <ListItem>
              <Body >
                <Grid>
                  <Col>
                    <Thumbnail source={{ uri: 'https://via.placeholder.com/30' }} />
                  </Col>
                  <Col>
                    <Text>{item.item.name}</Text>
                    <Text note>{item.item.price} $</Text>
                  </Col>
                  <Col>
                    <Text>{item.size} size</Text>
                    <Text>{item.price} $</Text>
                  </Col>
                </Grid>
              </Body>
            </ListItem>              
          }>
        </List>

Here i got list and the values coming from state.basket when i console.log the state in render function
the output is : {"5e822cc0daa03047c8ca7ff0": {"item": {"__v": 0, "_id": "5e822cc0daa03047c8ca7ff0", "name": "coke", "price": 5, "quantity": 50}, "price": 15, "size": "3"} which is correct output and i want to render each item’s name and price to the list but this not working, i tried to do with flatlist and mapping the object also it didn’t work or i did something wrong.
And this is the output of this.state :

{"basket": {"5e822cc0daa03047c8ca7ff0": {"item": [Object], "price": 15, "size": "3"}, "5e839d3b268ce30ef066cb84": {"item": [Object], "price": 50, "size": "2"}}, "isEmpty": false, "loading": false}

I think the problem is that the item is an object but when i googled it i couldn’t find any useful thing.
Thanks for the answers.

Since basket is an object you can still keep it as it is and use the object.keys() method to itterate through it:

 <List style={{ backgroundColor: '#fff' }} dataArray={Object.keys(this.state.basket)}
      renderRow={(key) =>
        <ListItem>
          <Body >
            <Grid>
              <Col>
                <Thumbnail source={{ uri: 'https://via.placeholder.com/30' }} />
              </Col>
              <Col>
                <Text>{this.state.basket[key].item.name}</Text>
                <Text note>{this.state.basket[key].item.price} $</Text>
              </Col>
              <Col>
                <Text>{this.state.basket[key].size} size</Text>
                <Text>{this.state.basket[key].price} $</Text>
              </Col>
            </Grid>
          </Body>
        </ListItem>              
      }>
    </List>

Tagged : / / /

Code Bug Fix: Most efficient way of importing files from children folders?

Original Source Link

I have a parent directory that contains children directories, where each contains an SVG component and I only need to import some of them. I’m currently importing all the components I need by doing this:

import FacebookIcon from 'project/icons/Facebook';
import TwitterIcon from 'project/icons/Twitter';
import DiscordIcon from 'project/icons/Discord';
import MediumIcon from 'project/icons/Medium';
import YoutubeIcon from 'project/icons/Youtube';

However this seems very verbose. Is there a less verbose way of doing this?

I thought about destructuring, but I wasn’t sure how to do this since each file is in a different folder.

Typically, you want to import similar components from a single source (you will get auto-complete too):

import {
  FacebookIcon,
  TwitterIcon,
  DiscordIcon,
  DiscordIcon,
  MediumIcon,
  YoutubeIcon,
} from "project/icons";

// Usage
<FacebookIcon/>

// Same
import Icons from './project/icons';

// Usage
const Icon = Icons.FacebookIcon;
<Icon/>

To achieve this, create index.js file in project/icons and make named export for each of the components.

export { default as FacebookIcon } from "./FacebookIcon";
...

Tagged : /