AndreasFaust / react-ticker

React Ticker is a lightweight, performant React component, that moves text, images and videos infinitely like a newsticker.
https://andreasfaust.github.io/react-ticker/
288 stars 50 forks source link

Can't get it to work as described, just rendering a div with a 0 in it #2

Open mengidd opened 5 years ago

mengidd commented 5 years ago

When I'm using this component as described it just returns a div with a 0 inside of it.

I tried various things always with the same result. A few of my attempts that I think should work according to the examples and the descriptions.

<Ticker>
  {(index) => (
    <div>Testing</div>
  )}
</Ticker>

or

<Ticker>
  <div>Testing</div>
</Ticker>

This is what's rendered, and nothing happens other than printing out the 0:

<div class="ticker" style="position: relative; overflow: hidden;">0</div>

Using React 16.7.

AndreasFaust commented 5 years ago

That's strange. React 16.7 works, at least here in my testing environment. Did you load react-ticker from npm? You definitely need to provide a function-as-child:

<Ticker>
  {({ index }) => (
    <div>Testing</div>
  )}
</Ticker>

By the way: The Render-Function-Argument has to be destructured (curly braces): ({ index }).

seckinbrke commented 5 years ago

same issue :)

MichaelTao commented 5 years ago

Having the same issue too. Gatsby V2

AndreasFaust commented 5 years ago

I tried to reproduce this error with Gatsby V2 dev, build and serve, but it just works. Please provide some information about your module-configuration, dev-environment and package.json.

MichaelTao commented 5 years ago

I'm fairly new to react so bear with me.

I created a blank Gatsby V2 and loaded the plugin and it works. I am trying to create a currency ticker. So I created a component called webticker.js.

`import React, { Component } from "react" import Ticker from 'react-ticker' import axios from "axios" import { Icon } from "tabler-react"

const flexContainer = { height: '100px', background: '#000', color: '#fff', padding: '10px', display: 'flex', alignItems: 'center', }

class WebTicker extends Component { state = { rates: [] }

componentDidMount() { this.rates() }

rates() { axios.get('<--api url goes here-->') .then(response => { this.setState({ rates: response.data }) console.log(this.state.rates) }) .catch(function (error) { console.log(error) }) }

render() { const rates = this.state.rates

return (
  <>
    <div style={flexContainer}>
      <Ticker>
        {rates.map(rate => {
          return (
            <Icon flag name={rate.iso.substring(0, 2).toLowerCase()} key={rate.iso} />
          )
        })}
      </Ticker>
    </div>
  </>
)

} }

export default WebTicker`

You mentioned

You definitely need to provide a function-as-child: By the way: The Render-Function-Argument has to be destructured (curly braces): ({ index }).

But I don't really understand it... but i did swap my code out for your example but it still returns a 0.

AndreasFaust commented 5 years ago

Try the following piece of code.

import React, { useEffect, useState } from 'react'
import Ticker from 'react-ticker'

/// /////////////////////////////////////
/// /////////////////////////////////////
// This part is just to mimic API Calls
/// /////////////////////////////////////
/// /////////////////////////////////////
/// /////////////////////////////////////

function getRandomIndex (min, max) {
  var offset = min
  var range = (max - min) + 1
  var randomNumber = Math.floor(Math.random() * range) + offset
  return randomNumber
}

const rates = [
  'Apple: 192.79',
  'Citigroup: 64.68',
  'General Electric: 10.10',
  'Google: 1.191',
  'Microsoft: 118.71'
]

function MakeFakeAPICall () {
  const number = getRandomIndex(0, 4)
  return new Promise((resolve) => {
    window.setTimeout(() => {
      resolve(rates[number])
    }, 500)
  })
}
/// /////////////////////////////////////
/// /////////////////////////////////////
/// /////////////////////////////////////

const GetRatesFromAPI = () => {
  // I am using the new React Hooks API here for brevity
  const [rate, setRate] = useState('')
  useEffect(() => {
    async function fetchData () {
      const rateFromAPI = await MakeFakeAPICall()
      setRate(rateFromAPI)
    }
    fetchData()
  }, [])
  // A placeholder is needed, to tell react-ticker, that width and height might have changed
  // It uses MutationObserver internally
  return rate
    ? <p className='rate'>{rate} +++ </p>
    : <p className='rate rate--placeholder'>Placeholder</p>
}

const WebTicker = () => (
  <Ticker
    offset='run-in'
    speed={10}
  >
    {() => <GetRatesFromAPI />}
  </Ticker>
)

export default WebTicker
AndreasFaust commented 5 years ago

I hope, you are familiar with the new Hooks API. I would strongly recommend to use it, because it makes things much easier. Here is the explanation of the code above:

AndreasFaust commented 5 years ago

I have updated the documentation by including the above example. The example in the docs differs from this example in loading a whole array of rates at once.

MichaelTao commented 5 years ago

Thank you for your explanation and examples! I'm going to give this a try and report back.

seanes commented 5 years ago

I tested your example with React 16.8.6 and it too only renders 0.

jjwallace commented 5 years ago

I am also just getting a 0 rendered

AndreasFaust commented 5 years ago

Please provide some information about your setup. The best way to solve this together would be a test-repo.

MedvedevWeb commented 5 years ago

This problem is caused by the zero width of container (div.ticker). You need just adding something like .ticker { width: 100%; } in your css.

jdrichardstech commented 4 years ago

Thanks @MedvedevWeb. I added the css and it worked perfectly.

joshuatuscan commented 4 years ago

I'm still getting a rendered 0 and have all elements inside the ticker with 100% width. I've tried testing static text as well. The craziest thing is that I have it running in another component and it works fine, but I can't get the second instance to render anything except 0.

kienhaminh commented 4 years ago

In case you are still getting a rendered 0 although edited your css, I have a solution for this issue. Why react-ticker return 0? Because the offsetWidth value is 0. You can file it in source code of react-ticker. (I think you should download source code and use it instead of installing by npm)

componentDidMount = () => {
      this.setState({
        width: this.tickerRef.current.offsetWidth,
        height: this.props.height,
      });
    window.addEventListener("resize", this.dOnResize);
  };

To solve it, I create a state value named restart (I'm using React Hooks). I pass an props named restart to Ticker component. Like this:

const [restart, setRestart] = useState(true);

<PageVisibility onChange={handleVisibilityChange}>
        {restart && pageIsVisible && (
          <Ticker
            height={40}
            move={move}
            restart={() => {
              setRestart(false);
            }}
          >
            {.....}
          </Ticker>
        )}
</PageVisibility>

In index.js file of react-ticker source, you check that if offsetWidth is equal 0, we run restart function.

componentDidMount = () => {
    if (this.tickerRef.current.offsetWidth === 0) {
      this.setState({
        width: window.innerWidth,
        height: this.props.height,
      });
      this.props.restart();
    } else {
      this.setState({
        width: this.tickerRef.current.offsetWidth,
        height: this.props.height,
      });
    }
    window.addEventListener("resize", this.dOnResize);
  };

And in the component use react-ticker, add this:

  useEffect(() => {
    if (!restart) setRestart(true);
  }, [restart]);

This way will make <Ticker> re-render when offsetWidth is equal 0. And... Ta-da, we never see that number 0. Hope you success!!

praveen-ranjan-ocl commented 4 years ago

I hope, you are familiar with the new Hooks API. I would strongly recommend to use it, because it makes things much easier. Here is the explanation of the code above:

  • React Ticker calls its function-as-child anytime it runs out of content. It does not matter, if this function is a static component or a component, that loads content from an API.
  • It is important, that you provide a placeholder during the loading time of the API-call, to trigger the mutation observer.
  • The component "GetRatesFromAPI" returns just one rate per load, which is a bit unhandy. I would return the whole array of rates on each load. I can provide another example, if needed.

If possible, Can you please provide an example where API returns whole array instead of one item on each call. In my case, I have list of items which I want to show one after another using mode=await.

praveen-ranjan-ocl commented 4 years ago

NoT really sure how to use this ticker if I have array of items that should appear as soon as the previous one has disappeared. It would be great if you can provide some examples.

AndreasFaust commented 3 years ago

For the record: Here’s the proof react-ticker is working with the latest react-version out of the box. https://codesandbox.io/s/quizzical-lehmann-nqy7w No discussions anymore. From now on unfriendly requests and rude, unproved claims will be blocked unanswered. Open-Source is not about ranting and giving orders; it’s about helping each other out and solving problems together in solidarity. https://docs.github.com/en/free-pro-team@latest/github/site-policy/github-community-guidelines

bennchong commented 3 years ago

Had this issue when is not at the root of the React Component. Eg:

<div>
  <Ticker>
     <p> hi </p>
  </Ticker>
</div>

Simple fix is to remove the parent div wrapper

timothydelter commented 3 years ago

I couldn't get it working by setting the width of .ticker to 100%. But when I resize the window the ticker starts. So I added this to my React component to emulate a window resize and it now works.


  useEffect(() => {
    var resizeEvent = new Event("resize");
    window.dispatchEvent(resizeEvent);
  }, []);
ghost commented 3 years ago

One of the ticker parent container must be 100% width when working with flex

ryangall7 commented 2 years ago

ya same here, running gatsby 4 and react 17. It will intermitantly start working on every resize event.

Cookiesale commented 2 years ago

I'm struggling with this 0 issue as well. All parents are 100%. The simulated refresh works on localhost, but does not work when hosted on a server.

I'd do what Kaneha suggested, but I'm not familiar with manually installation.

Surely there must be a solution

AryanJ-NYC commented 1 year ago

Just use https://www.npmjs.com/package/react-fast-marquee and be happy.