0

I'm attempting to implement useContext in various areas of my application starting with the below.

This excerpt references four separate part of the UI that nonetheless require information relating to an event. At the moment I'm prop drilling and would like to get rid of this. Given all the examples I'm confused as to whether I can declare the context within the area of the excerpt, or if it should be a separate file. And other questions like how do you manage contexts within a mapped loop.

In the below case I'm looking for some kind of filteredEntryContext (or for less confusion entryContext).

This context needs to be consumed by EntryIcon, TypeIcon, FavIcon, NewIcon and GovIcon.

Excerpt from Entries.js

          {entries.filter(entry => entry.publishdate
              .includes(date))
              .map(filteredEntry =>(


                    <div className="entry" key={filteredEntry.id}>
                      <div>
                        <span><EntryTitle url={filteredEntry.url} title={filteredEntry.title} domain={filteredEntry.domain}/></span>
                        <span><TypeIcon type={filteredEntry.type}/></span>
                        <span>   </span>
                        <span><FavIcon favourite="false"/></span>
                        <span>   </span>
                        <span><NewIcon addeddate={filteredEntry.addeddate}/></span>
                        <span>   </span>
                        <span><GovIcon domain={filteredEntry.domain}/></span>
                      </div>
                    <div className="entrysubtext text-muted small">{filteredEntry.description}</div>
                  </div>
              )
            )
          }

EntryTitle.js

import React from 'react';
import '../../App.css'

function EntryTitle (props){

  return (
    <>
      <span className="entrytitle"><a href={props.url} target="_blank" rel="noopener noreferrer">{props.title}</a></span>
      <span className="text-muted small"> {props.domain}</span>
    </>
  )
}

export default EntryTitle

GovIcon.js

import React from 'react'
import '../../App.css'

function IconSwitch(props) {
  let domain = props.domain
  let isGov = false

  if (domain.includes('.gov'))
    isGov = true

  switch(isGov) {
    case true:
      return(<span class="badge float-right badge-warning entryicon">G</span>)
    default:
      return null;
    }
  }

function GovIcon (props){

  return (
    <>
      <IconSwitch domain={props.domain}/>
    </>
  )
}

export default GovIcon

TypeIcon.js

import React from 'react';
import '../../App.css'

function IconSwitch(props) {
  switch(props.value) {
    case 'article':
      return  <span><i  className="fa fa-file-text float-right entryicon" aria-hidden="true"></i></span>
      //return 'fa fa-file-text';
    case 'video':
      return  <span><i  className="fa fa-video-camera float-right icon-red entryicon" aria-hidden="true"></i></span>
      //return 'fa fa-video-camera';
    case 'audio':
      return  <span><i  className="fa fa-headphones float-right icon-orange entryicon" aria-hidden="true"></i></span>
      case 'forum':
        return  <span><i  className="fa fa-comments float-right icon-blue entryicon" aria-hidden="true"></i></span>
    default:
      return 'foo';
  }
}


function TypeIcon (props){

  return (
    <>
      <IconSwitch value={props.type} />
    </>
  )
}

export default TypeIcon
TheMightyLlama
  • 996
  • 1
  • 14
  • 38
  • https://stackoverflow.com/questions/41030361/how-to-update-react-context-from-inside-a-child-component this looks to be what you need. – Wen W Oct 12 '20 at 12:44

1 Answers1

0

Fixed this.

I modified the Entries.js file with an export at the top of the page. Declaring a new constant EntryContext.

export const EntryContext = React.createContext()

The mapped section further down now has the functions being called wrapped in a <EntryContext.Provider value={filteredEntry}> pair of tags.

    <EntryContext.Provider value={filteredEntry}>
      <span className="div-left"><EntryTitle url={filteredEntry.url} title={filteredEntry.title} domain={filteredEntry.domain}/></span>
      <span><TypeIcon /></span>
      <span>   </span>
      <span><FavIcon favourite="false"/></span>
      <span>   </span>
      <span><NewIcon addeddate={filteredEntry.addeddate}/></span>
      <span>   </span>
      <span><GovIcon domain={filteredEntry.domain}/></span>
    </EntryContext.Provider>

The other files now import the context from Entries.js

import {EntryContext} from '../Entries'

And they have the relevant sections in the return() statement surrounded with <EntryContext.Consumer> tags.

GovIcon component

import React from 'react'
import '../../App.css'
import {EntryContext} from '../Entries'



function IconSwitch(props) {
  let domain = props.domain
  let isGov = false

  if (domain.includes('.gov'))
    isGov = true

  switch(isGov) {
    case true:
      return(<span class="badge float-right badge-warning entryicon">G</span>)
    default:
      return null;
    }
  }

function GovIcon (){

  return (
    <EntryContext.Consumer>
    {(values) =>
      <IconSwitch domain={values.domain}/>
    }
    </EntryContext.Consumer>
  )
}

export default GovIcon
TheMightyLlama
  • 996
  • 1
  • 14
  • 38