react-autosuggest icon indicating copy to clipboard operation
react-autosuggest copied to clipboard

Uncaught TypeError: Cannot read property 'trim' of undefined

Open jopcode opened this issue 7 years ago • 20 comments

When i type in the search bar this show me the results, but when i click on a value the console give me this 'Uncaught TypeError: Cannot read property 'trim' of undefined', and my app don't reload the view until I deleted the value on search bar. Any idea or solution? ( sorry for my bad english)

Screenshots:

before type on the search bar:

image

When i type on search bar style (doesn't matter) image

And when i click on a value(the progress bar and the time don't reload until after deleted value on search bar): image

When i deleted the value on search bar: image

First TypeError: image

And the last TypeError:

shouldRenderSuggestions	@	AutosuggestContainer.js:174
componentWillReceiveProps	@	Autosuggest.js:72
(anonymous function)	@	ReactCompositeComponent.js:611
measureLifeCyclePerf	@	ReactCompositeComponent.js:75
updateComponent	@	ReactCompositeComponent.js:610
receiveComponent	@	ReactCompositeComponent.js:547
receiveComponent	@	ReactReconciler.js:125
_updateRenderedComponent	@	ReactCompositeComponent.js:754
_performComponentUpdate	@	ReactCompositeComponent.js:724
updateComponent	@	ReactCompositeComponent.js:645
receiveComponent	@	ReactCompositeComponent.js:547
receiveComponent	@	ReactReconciler.js:125
_updateRenderedComponent	@	ReactCompositeComponent.js:754
_performComponentUpdate	@	ReactCompositeComponent.js:724
updateComponent	@	ReactCompositeComponent.js:645
receiveComponent	@	ReactCompositeComponent.js:547
receiveComponent	@	ReactReconciler.js:125
updateChildren	@	ReactChildReconciler.js:109
_reconcilerUpdateChildren	@	ReactMultiChild.js:208
_updateChildren	@	ReactMultiChild.js:312
updateChildren	@	ReactMultiChild.js:299
_updateDOMChildren	@	ReactDOMComponent.js:936
updateComponent	@	ReactDOMComponent.js:754
receiveComponent	@	ReactDOMComponent.js:716
receiveComponent	@	ReactReconciler.js:125
_updateRenderedComponent	@	ReactCompositeComponent.js:754
_performComponentUpdate	@	ReactCompositeComponent.js:724
updateComponent	@	ReactCompositeComponent.js:645
receiveComponent	@	ReactCompositeComponent.js:547
receiveComponent	@	ReactReconciler.js:125
updateChildren	@	ReactChildReconciler.js:109
_reconcilerUpdateChildren	@	ReactMultiChild.js:208
_updateChildren	@	ReactMultiChild.js:312
updateChildren	@	ReactMultiChild.js:299
_updateDOMChildren	@	ReactDOMComponent.js:936
updateComponent	@	ReactDOMComponent.js:754
receiveComponent	@	ReactDOMComponent.js:716
receiveComponent	@	ReactReconciler.js:125
_updateRenderedComponent	@	ReactCompositeComponent.js:754
_performComponentUpdate	@	ReactCompositeComponent.js:724
updateComponent	@	ReactCompositeComponent.js:645
performUpdateIfNecessary	@	ReactCompositeComponent.js:561
performUpdateIfNecessary	@	ReactReconciler.js:157
runBatchedUpdates	@	ReactUpdates.js:150
perform	@	Transaction.js:140
perform	@	Transaction.js:140
perform	@	ReactUpdates.js:89
flushBatchedUpdates	@	ReactUpdates.js:172
closeAll	@	Transaction.js:206
perform	@	Transaction.js:153
batchedUpdates	@	ReactDefaultBatchingStrategy.js:62
enqueueUpdate	@	ReactUpdates.js:200
enqueueUpdate	@	ReactUpdateQueue.js:24
enqueueSetState	@	ReactUpdateQueue.js:219
ReactComponent.setState	@	ReactComponent.js:63
handleSongPlaying	@	App.js:55
whileplaying	@	index.js:153
SMSound._whileplaying	@	soundmanager2.js:3421
SMSound._onTimer	@	soundmanager2.js:2953
(anonymous function)	@	soundmanager2.js:4106
(anonymous function)	@	soundmanager2.js:3852

The line 55 of my app.js:

handleSongPlaying(audio) {
        this.setState({
            elapsed: this.parseMilliseconds(audio.position),
            total: this.parseMilliseconds(audio.duration),
            position: audio.position / audio.duration
        })
    }

The states;

this.state = {
            track: {
                stream_url: '',
                title: '',
                artwork_url: ''
            },
            playStatus: Sound.status.PLAYING,
            elapsed: '00:00',
            total: '00:00',
            position: 0,
            playFromPosition: 0,
            autoCompleteValue: '',
            tracks: []
        }

Any idea or solution for this? 🤕

jopcode avatar May 21 '17 16:05 jopcode

It's hard to say from the information you provided what's wrong.

This error could appear if somehow inputProps.value ends up not being a string. Could you verify that it is always a string?

If you still can't figure this out, could you create a Codepen that reproduces the issue?

moroshko avatar May 22 '17 02:05 moroshko

@moroshko where i could verify that is always a string?,this is mi full code:

import React, { Component } from 'react'
import ReactDom from 'react-dom'
import Axios from 'axios'
import Sound from 'react-sound'
import update from 'react-addons-update'

import Details from '../components/Details'
import Player from '../components/Player'
import Progress from '../components/Progress'
import Search from '../components/Search'

export default class App extends Component {
    constructor() {
        super()
        this.clientId = 'H1mb6cSHjS0dg9AvapNHmczj9zFtbcgJ'
        this.state = {
            track: {
                stream_url: '',
                title: '',
                artwork_url: ''
            },
            playStatus: Sound.status.PLAYING,
            elapsed: '00:00',
            total: '00:00',
            position: 0,
            playFromPosition: 0,
            autoCompleteValue: '',
            tracks: []
        }
    }

    componentDidMount() {
        this.randomSong();
    }

    onSuggestionsClearRequested() {

    }

    handleChange(event, value) {
        this.setState({ autoCompleteValue: value.newValue })
        let _this = this

        Axios.get(`https://api.soundcloud.com/tracks?client_id=${this.clientId}&q=${value.newValue}`)
            .then((res) => {
                _this.setState({ tracks: res.data })
                console.log(_this.state.track)
            })
            .catch((err) => {
                console.log(err)
            })
    }

    handleSelect(value, item) {
        this.setState({ autoCompleteValue: value.item, track: value })
    }

    handleSongPlaying(audio) {
        this.setState({
            elapsed: this.parseMilliseconds(audio.position),
            total: this.parseMilliseconds(audio.duration),
            position: audio.position / audio.duration
        })
    }

    handleSoundFinished() {
        this.randomSong()
    }

    parseMilliseconds(time) {
        let hours = Math.floor(time / 3600000)
        time = time % 3600000

        let minutes = Math.floor(time / 60000)
        time = time % 60000

        let seconds = Math.floor(time / 1000)
        time = Math.floor(time % 1000)

        return (
            (minutes < 10 ? '0' : '') + minutes + ':' +
            (seconds < 10 ? '0' : '') + seconds
        )
    }

    togglePlay() {
        if (this.state.playStatus == Sound.status.PLAYING) {
            this.setState({ playStatus: Sound.status.PAUSE })
        } else {
            this.setState({ playStatus: Sound.status.PLAYING })
        }
    }

    stop() {
        this.setState({ playStatus: Sound.status.STOPPED })
    }

    forward() {
        this.setState({ playFromPosition: this.state.playFromPosition += 1000 * 10 })
    }

    backward() {
        this.setState({ playFromPosition: this.state.playFromPosition -= 1000 * 10 })
    }

    randomSong() {

        let _this = this
        Axios.get('https://api.soundcloud.com/playlists/126995930?client_id=' + this.clientId)
            .then((res) => {
                const trackLength = res.data.tracks.length
                const randomNumber = Math.floor((Math.random() * trackLength) + 1)

                _this.setState({ track: res.data.tracks[randomNumber] })

                let track = _this.state.track
                track['artwork_url'] = _this.state.track.artwork_url.replace('large', 't500x500')
                _this.setState({ track: track })


            })
            .catch((err) => {
                console.log(err)
            })
    }

    formatUrl(url) {
        return `${url}?client_id=${this.clientId}`
    }

    render() {
        return (
            <div>
            <Sound
                url={this.formatUrl(this.state.track.stream_url)}
                playStatus={this.state.playStatus}
                onPlaying={this.handleSongPlaying.bind(this)}
                playFromPosition={this.state.playFromPosition}
                onFinishedPlaying={this.handleSoundFinished.bind(this)} />
            <Search
                autoCompleteValue={this.state.autoCompleteValue}
                tracks={this.state.tracks}
                handleSelect={this.handleSelect.bind(this)}
                handleChange={this.handleChange.bind(this)}
                onSuggestionsClearRequested={this.onSuggestionsClearRequested.bind(this)}
            />
            <section>
                <img src={this.state.track.artwork_url} width="400" height="225" />
                <header>
                    <Details
                        elapsed={this.state.elapsed}
                        title={this.state.track.title} />
                    <Player
                        togglePlay={this.togglePlay.bind(this)}
                        stop={this.stop.bind(this)}
                        forward={this.forward.bind(this)}
                        backward={this.backward.bind(this)}
                        random={this.randomSong.bind(this)}
                        playerStatus={this.state.playStatus}
                    />
                </header>
                <Progress
                    position={this.state.position} />
            </section>
            </div >
        )
    }

}

i am a bit new on react

jopcode avatar May 22 '17 06:05 jopcode

You can check this in your AutosuggestContainer.js, or maybe your Search.js file.

What you should be checking is that the value that you pass as an argument to inputProps is a string value.

If you followed the examples in the doc, you should have something like this :

const inputProps = {
      placeholder: 'Type a programming language',
      value,
      onChange: this.onChange
};

where value is set by

const getSuggestionValue = suggestion => suggestion.name;

If you find the place where the value is set, you can check that you never return a value that is not a string. As an example, I had the same problem because I was returning suggestion.name but my data was on a different model, so I had to change to something like suggestion.myobject.myproperty.

thisfrontenddev avatar May 22 '17 10:05 thisfrontenddev

I'm having the same issue as described here, except I'm 100% correct that my inputProps.value is always string. Using 9.1.0 version of react-autosuggest.

m-czarnik avatar Jun 22 '17 14:06 m-czarnik

@Mateusz-Czarnik Could you create a Codepen that reproduces the issue?

moroshko avatar Jun 22 '17 14:06 moroshko

Yes, I will try tomorrow.

m-czarnik avatar Jun 22 '17 15:06 m-czarnik

I stumbled accross the same error. In my case was not a bug, but a misunderstanding of the onChange handler:

I used an onChange handler as I would on every other input:

onChange = (event) => {
  this.setState({ value: event.target.value })
}

While the Autosuggest component provides the new value not within event.target, but in the second parameter:

onChange = (event, { newValue }) => {
  this.setState({ value: newValue })
}

I just submitted a minor PR that includes a hint in the documentation: https://github.com/moroshko/react-autosuggest/pull/396

philipstanislaus avatar Jul 02 '17 12:07 philipstanislaus

@paliwalgaurav can you show your onChange handler?

philipstanislaus avatar Aug 04 '17 07:08 philipstanislaus

Throwing this up here for anyone else that may run into this error. I ran into this and it ended up being my getSuggestionValue const. I had:

const getSuggestionValue = suggestion => {
  suggestion.username;
};

but it should have been:

const getSuggestionValue = suggestion => suggestion.username;

daffinito avatar Aug 13 '17 23:08 daffinito

This worked for me , in case somebody needs it

onChange = (event, { newValue }) => {
        this.setState({
            value: typeof newValue !== 'undefined' ? newValue : '',
        });
};

makostom avatar Nov 03 '17 13:11 makostom

Same here, the problem is when we have a value like null or undefined if i set my value to empty string '' it works,

Autossugest.js line 280

return (valueBeforeUpDown || value).trim();

it should be some thing like this

const newValue = valueBeforeUpDown || value; 
return newValue ? newValue.trim() : null;

renanborgez avatar Jan 02 '18 18:01 renanborgez

Hi @philipstanislaus i got undefined variable newValue. This is my code:

<Input type="text" placeholder="Username" autoComplete="username" name="username" onChange={(e, {newValue}) => this.setState({username: newValue})}/>

dafapramudya avatar Nov 21 '18 04:11 dafapramudya

@dafapramudya code looks fine – did you try this solution? https://github.com/moroshko/react-autosuggest/issues/368#issuecomment-341709014

philipstanislaus avatar Nov 21 '18 11:11 philipstanislaus

I've been getting this error on the getSuggestionValue callback. Turned out, this.setState wasn't updating my state variable for some reason. The callback got invoked. The context is correct. Everything should work, but this.setState just wasn't working properly. Perhaps, it's the async nature of this.setState and my call got queued, but I don't know for certain if it was or not.

I ended up assigning the value to my state variable directly and calling this.forceUpdate() directly afterwards in my callback. I know it's not the cleanest solution, but it works. Anyone else running into this problem should check to make sure this.setState is actually updating your variable.

I don't know if the issue is being caused by this component, but I post this in case someone else runs into this problem.

u4yk avatar Dec 09 '18 11:12 u4yk

Throwing this up here for anyone else that may run into this error. I ran into this and it ended up being my getSuggestionValue const. I had:

const getSuggestionValue = suggestion => {
  suggestion.username;
};

but it should have been:

const getSuggestionValue = suggestion => suggestion.username;

this solved my case, thank you , can you explain what is the difference between them, i am new in react and cant see any difference

fozerol avatar Dec 31 '18 07:12 fozerol

@fozerol IIRC in the first example, the arrow function is just executing suggestion.username, which does nothing since it's a string. Without the braces, like in the second example, suggestion.username gets returned, which is why it works and the first one doesn't. I never use the non-braced version and explicitly return my values; so, I might not be the best to explain this, but that's how it works if memory serves.

u4yk avatar Dec 31 '18 08:12 u4yk

What fixed it for me is the following:

 const getSuggestions = (input:any) => {
     const inputValue = input.value.trim().toLowerCase();
     const inputLength = inputValue.length;
     return inputLength === 0 ? [] : data.filter(lang =>
       lang.name.toLowerCase().slice(0, inputLength) === inputValue
     );
 };

invot avatar Jul 25 '19 16:07 invot

What fixed it for me is the following:

 const getSuggestions = (input:any) => {
     const inputValue = input.value.trim().toLowerCase();
     const inputLength = inputValue.length;
     return inputLength === 0 ? [] : data.filter(lang =>
       lang.name.toLowerCase().slice(0, inputLength) === inputValue
     );
 };

tried this solution but I still have the same error

ghost avatar Aug 25 '19 13:08 ghost

The issue is the with onChange handler only. I changed it to the following:

<Autosuggest
         suggestions={nameSuggestions}
         onSuggestionsFetchRequested={onSuggestionsFetchRequested}
         onSuggestionsClearRequested={onSuggestionsClearRequested}
         getSuggestionValue={getSuggestionValue}
         renderSuggestion={renderSuggestion}
         inputProps={{
           value: name,
           onChange: (e, { newValue }) => setName(newValue),
         }}
       />

Shivendra30 avatar Nov 26 '19 01:11 Shivendra30

having the same problem dont know how to solve this

function checkRequired(input) { input.forEach(function(input) { if (input.value.trim() === '') { showError(input, ${getFieldName(input)} is required); } else { showSuccess(input); } }); }

Phinah avatar Dec 02 '20 19:12 Phinah