Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Click link to scroll to specific section react.js

I have implemented a side menu that has a link tag for each section but I am unsure how to implement the functionality when clicking on them the user is taken to the specific section. I understand how to do it if the it was in the same component and if I was generating the sections in a normal fashion but I am doing it in a different way and I am unsure how to implement something like react-scroll or scrollchor.

Here I am generating the sections with buildTree by mapping over some data I have in another file.

export default class CheckboxGroup extends PureComponent {
  constructor(props) {
    super(props);
    this.checkboxState = new Map();
    this.state = {
      checkboxState: new Map(),
    };
  }

  static propTypes = {
    data: PropTypes.any.isRequired,
    onChange: PropTypes.func.isRequired,
    counter: PropTypes.number,
  };

  treeCheckboxOnChange = (parentLabel, id, checked) => {
    this.checkboxState = this.checkboxState.setIn([parentLabel, id], checked);
    this.setState({
      checkboxState: this.checkboxState,
    });
  };

  mapParents = (counter, child) => {
    const parentLabel = child.get('label');
    return (
      <li key={child.get('name')} className='field'>
      <SegmentHeader style={segmentStyle} title={child.get('label')} icon={child.get('icon')}>
        <div className='fields' style={zeroMargin}>
          <div className='four wide field'>
            <TreeCheckbox
              label={`Grant ${child.get('label')} Permissions`}
              parentLabel={parentLabel}
              counter={counter}
              onChange={this.treeCheckboxOnChange}
            />
            {child.get('items') && this.buildTree(child.get('items'), counter + child.get('name'), parentLabel)}
          </div>
          <div className='twelve wide field'>
            <GrantDropdown checkboxState={this.state.checkboxState.get(parentLabel, new Map())} label={child.get('label')} childItems={child.get('items')}/>
          </div>
        </div>
      </SegmentHeader>
    </li>
    );
  };

  mapDataArr = (counter, parentLabel) => (child) => (
    (counter === 0) ?
      this.mapParents(counter, child)
      :
      <li key={child.get('name')}>
        <TreeCheckbox label={child.get('label')} parentLabel={parentLabel} onChange={this.treeCheckboxOnChange}/>
        {child.get('items') && this.buildTree(child.get('items'), counter + child.get('name'), parentLabel)}
      </li>
  )

  buildTree = (dataArr, counter, parentLabel) => (
    <ul key={counter} style={listStyle}>
      {dataArr.map(this.mapDataArr(counter, parentLabel))}
    </ul>
  )

  render() {
    return (
      <div className='tree-view'>
        {this.buildTree(this.props.data, this.props.counter)}
      </div>
    );
  }
}

I have used the same technique to map over the data to create my sticky sideNav.

export default class SideNav extends Component {

  static propTypes = {
    data: PropTypes.any.isRequired,
    counter: PropTypes.number,
  };

  mapPermissionNames = (counter, child) => (
    <li key={child.get('name')}>
      <Link>{child.get('label')}</Link>
    </li>
  )

  mapDataArr = (counter) => (child) => (
    (counter === 0) ?
      this.mapPermissionNames(counter, child)
      :
      <li key={child.get('name')}>
        <Link>{child.get('label')}</Link>
      </li>
  )

  buildTree = (dataArr, counter) => (
    <ul key={counter} style={listStyle}>
      {dataArr.map(this.mapDataArr(counter))}
    </ul>
  )

  render() {
    return (
      <div className='tree-view'>
        {this.buildTree(this.props.data, this.props.counter)}
      </div>
    );
  }
}

and this is the parent where they both are rendered.

export default class LocationPermissions extends AbstractSettingsComponent {

  handlePermissionChange = (e, { value }) => {
    this.updatePerson('locationPermissions', value);
  }

  updateCheckmarks = (id, checked) => {
    const { currentPerson } = this.props;
    if (checked && !currentPerson.get('permissions').includes(id)) {
      this.updatePerson('permissions', id, true);
    } else if (!checked && currentPerson.get('permissions').includes(id)) {
      this.filterItem(['currentPerson', 'permissions'], id, 1);
    }
  }

  render() {
    const { currentPerson } = this.props;
    return (
      <div>
        <SegmentHeader icon='building' title='Location Permissions'>
          <div className='two fields' style={zeroMarginBottom}>
            <div className='field'>
              <OptionSelector
                label={`Grant ${this.getPerson()} permissions for...`}
                options={this.getPermissionOptions()}
                value={currentPerson.get('locationPermissions') || 0}
                onChange={this.handlePermissionChange}
              />
            </div>
            {currentPerson.get('locationPermissions') === 2 &&
              <div className='field'>
                <label>Grant Location Admin Permissions For</label>
                <LocationMultiSelect name='Every' {...this.props}/>
              </div>
            }
          </div>
        </SegmentHeader>
        <StickyContainer>
        {currentPerson.get('locationPermissions') === 3 &&
          <div className='fields'>
            <div className='three wide field'>
              <Sticky style={{ paddingTop: '15px' }}>
                <SideNav
                  data={permissionSections}
                  counter={0}
                />
              </Sticky>
            </div>
            <div className='twelve wide field'>
            <CheckboxGroup
              data={permissionSections}
              counter={0}
              onChange={this.updateCheckmarks}
            />
          </div>
        </div>
        }
        </StickyContainer>
      </div>
    );
  }
}

I am having trouble understanding how to implement something like react-scroll or scrollchor or react-router link tags to be able to click on the section and scroll to that section on the page. Any suggestions would be very welcome.

like image 561
StuffedPoblano Avatar asked Sep 12 '17 15:09

StuffedPoblano


3 Answers

Here is how I did it without complicated steps or 3rd party libraries

1- create a div with an onClick event and add the window.location.replace to replace the current URL with the desired one. here is an example

<div onClick={() => window.location.replace("/#about")}>
<span>go to about</span>
</div>

2- in your section add the Id you are trying to go.

<h2 id="about">About</h2>

and all done without 3rd party libraries. cheers.

like image 134
jerryurenaa Avatar answered Oct 19 '22 07:10

jerryurenaa


Used this way working fine (react js)

<Link to='/home/#section1'></Link>

and other page put a id name

id={'section1'}
like image 30
shanmuga Rajan Avatar answered Oct 19 '22 09:10

shanmuga Rajan


I was able to just use the browser supported way by doing:

<a href={`#${child.get('label')}`}>{child.get('label')}</a>

And then just add an id to the list element.

like image 3
StuffedPoblano Avatar answered Oct 19 '22 09:10

StuffedPoblano