react-scrollspy
react-scrollspy copied to clipboard
List Items generated programmatically
Hi @makotot ,
first of all thanks for the beautiful component! I took a look at the issues unsuccessfully. I'd like to make react-scrollspy work together with programmatically generated list items. Could you plese provide me some info about the feasability. Thanks in advance. Here you'll find a reference code sample to give you a rough idea of what I'm talking:
const Parent = ({options}) => (
<Scrollspy
items={ ['news', 'mission', 'whatwedo', 'competences'] }
currentClassName="active">
{options.map((x, idx) => <Child item={x} key={idx}/>)}
</Scrollspy>
);
const Child = ({item}) => (
<li>
<a href={item.anchor}>{item.label}</a>
</li>
);
What I came up with as a work-around is to intercept Scrollspy onUpdate method. I hook into the onUpdate method in order to update a newly created active attribute in the hash array of Scrollspy <ul> option list items.
I'll welcome a better approach.
Best, Luca
@lanceschi Sorry, I have no time at this weekday, so I'll check the issue at this weekend.
I think using onUpdate is only way to accomplish your needs. Unfortunately, this lib is not thought about generated list items at least now.
-
With generated list items,
currentClassNamedoes not pass to target list element.
-
With static list items,
currentClassNamedefinitely passes to target.
@makotot thanks! Got it. I guess you can close this issue now.
If you're planning on extending this lib in order to support programmatically generated option items, then let me know. I'd like to help and contribute.
Kind regards, Luca
@lanceschi I am also trying to use this library with generated list items. Would you mind sharing how you implemented the work-around you mentioned above? I am trying to console.log the output of any variables in the onUpdate event, but I don't see anything...
Hi @gtwilliams03 onUpdate is to deliver a parameter (object). Here you'll find some code in order to give you an idea of how I implemented the workaround:
Partial JSX markup within the component render function
<Scrollspy
items={this.optionIdList}
offset={-160}
onUpdate={this.setActiveOption}
currentClassName="active">
{this
.state
.options
.map((x, idx) => <MenuOption item={x} key={idx}/>)}
</Scrollspy>
OnUpdate event handler function
I read and map the list of the menu options (array of objects) from this.props.options and eventually set the active flag and set as a state of the component. this.state.options is used to programmatically render the menu options as you can see in the above jsx snippet.
setActiveOption(e) {
if (!e) return;
const optHash = this
.props
.options
.map(x => (x.anchor === `#${e.id}`)
? {
...x,
active: true
}
: x);
this.setState({opts: optHash});
}
I hope it'll help you!
Best, Luca
@lanceschi Thank you for the note! I get undefined in the onUpdate handler when I write out e to the console (only when the component mounts, and handleScrollSpyChange is not called if the page is scrolled (I am sure I am making a basic mistake...):
handleScrollSpyChange(e) {
console.log(e)
}
render() {
const { items } = this.props
return (
<div>
<Scrollspy items={items.map(i => i.abbreviation)} offset={-100}
currentClassName='active' onUpdate={this.handleScrollSpyChange}>
{items.map(i => <li key={`${i.abbreviation}`}><a href={`#section-${i.abbreviation}`}>{i.abbreviation}</a></li>)}
</Scrollspy>
</div>
)
}
@makotot can you:
- further explicit what's inside
itemsattribute ofScrollspy; - define your component
constructorfunction? Do you bind thathandleScrollSpyChangefunction?
Best, L
Was so stumped that my generated markup wasn't working. This would be good to put in the docs on how to use with programmatically created list objects.
I realised that it if you map through an array and return the JSX - not using a functional Component it works. I'm intrigued as to why this happens? 🤷♂️🤓
const items = ['section-1', 'section-2', 'section-3']
const links = items.map(link => {
return <li><a href={link}>{link}</a></li>
})
...
<Scrollspy
items={ ['section-1', 'section-2', 'section-3'] }
currentClassName="is-current"
className="c-side-nav__list nav-list"
style={ {fontWeight: 300} }
offset={ -20 }
onUpdate={
(el) => {
console.log(el)
}
}
>
{links}
</Scrollspy>
Related to https://github.com/makotot/react-scrollspy/issues/96