6

I'm currently coding a React -typescript App for practising FluentUI (a.k.a Fabric). Issue appears with my App.tsx component.

import React, { useContext, useState } from 'react';
import logo from './logo.svg';
import './App.css';
import Search from './components/Search';
//import CategoriasProvider from './components/Context/CategoriasContext';
import Title from './components/Title';
import { ListGhostingExample } from '../src/components/DrinkList';
import { PrimaryButton } from 'office-ui-fabric-react';
import { CategoriasContext,  ICategoriasContextInterface } from './components/Context/CategoriasContext';
import CategoriasProvider from './components/Context/CategoriasContext';
import axios from 'axios';
import './components/DrinkList.css'
import './components/Search.css'

interface IApp{
  items:ICategoriasContextInterface[],
  renderList:boolean
  
}

const App =()=> {
 
  const contextValues=useContext(CategoriasContext);
  
  return(
<CategoriasProvider>
    <div className="App">
     
        <div className="search">
          <Search name={contextValues?.name} image={contextValues?.image} thumbnail={contextValues?.thumbnail} />
        </div>

     
    </div>
    </CategoriasProvider>
  );
}


export default App;

CategoriasProvider comes from a Context (CategoriasContext.tsx ). CategoriasProvider has the mentioned error Inside of CategoriasProvider there's a Search.tsx Component.Search's works as a "wrapper". Code is:

import React, { useEffect, useState } from 'react';
import { SearchBox,ISearchBoxStyles  } from 'office-ui-fabric-react/lib/SearchBox';
import { PrimaryButton, IContextualMenuProps, Stack, IStackTokens, StackItem, initializeIcons } from 'office-ui-fabric-react';
import { ComboBox, DefaultPalette, Dropdown, DropdownMenuItemType, IComboBoxOption, IDropdownOption, IDropdownStyles, IStackItemStyles, SelectableOptionMenuItemType, Toggle } from '@fluentui/react';
import {  getGlassesOriginal } from './Utils/Utils';
import axios from 'axios';
import '../Search.css';
import { CategoriasContext, ICategoriasContextInterface } from './Context/CategoriasContext';

initializeIcons();
const Search = (props:ICategoriasContextInterface) => {

  //State
  const [textContent, setTextContent] = useState(""); 
  const [textBoxDisabled,disableTextBox]=useState(false);
  const [comboBoxDisabled,disableComboBox]=useState(true);
  const CategoriasContextInSearch=React.useContext(CategoriasContext);
  
  const setTextContentInstate = (e: any) =>{  
    console.log("Contenido de e" + e.target.value);
    setTextContent(e.target.value);  
}

  const showMessageInConsole = ():void => {
    
  console.log(textContent);
  setTextContent(""); 

}

    // Example formatting
    const stackTokens: IStackTokens = { childrenGap: 20 };

    const searchBoxStyles: Partial<ISearchBoxStyles> = { root: { width: 200 } };

    const dropdownStyles: Partial<IDropdownStyles> = {
      dropdown: { width: 200 },
    };
    
    const options: IDropdownOption[] = [
      { key: 'glasses', text: 'Glasses', itemType: DropdownMenuItemType.Header },
     
     
    ];
   
    function getGlasses () {
     
      let outputArray:string[] = [];
      console.log("getGlasses");
      
  axios
      .get("https://www.thecocktaildb.com/api/json/v1/1/list.php?g=list")
      .then((response)=>{
  
          let responseDataJson=response.data.drinks;       
          for (let element in responseDataJson) {    
            options.push({key:responseDataJson[element].strGlass,text:responseDataJson[element].strGlass});       
          }
         }
              
  )

  return outputArray;
  }

 
  function selectSearch(){

 
    if(textBoxDisabled){
   
      disableTextBox(false);
      disableComboBox(true);
    } else {
     
      disableTextBox(true);
      disableComboBox(false);
    
    };
  }
   
   
    useEffect(() => {

      //TODO: No se debería llamar siempre a esta función. Solamente cuando se activa el sistmea de búsqueda (y además, cachearlo)
      getGlasses()
      
  
    });

     
    return(
    
                 <div className="wrapper">
                   <div className="one"> <Toggle  onClick={selectSearch}/></div>
                            
                                
                                    <div className="two">
                                    {
                                      <SearchBox 
                                      name="searchBox"
                                      className="searchBox"  
                                      styles={searchBoxStyles} 
                                      placeholder="Cheers!" 
                                      onChange={setTextContentInstate} 
                                      value={textContent}
                                      disabled={textBoxDisabled}
                                      />
                                    }
                                      </div>
                                      <div className="three">
                                      <Dropdown
                                    placeholder="Select a glass"
                                    options={options}
                                    styles={dropdownStyles}
                                    disabled={comboBoxDisabled}
                                      />
                                     
                                      </div>
                                      <div className="four">
                                      <div className="primaryButton">
                                        <PrimaryButton text="Search"   onClick={showMessageInConsole}/>
                                        </div>

                                      </div>
                                      
                                 

                   </div>
                    
                       

                                
            
            
       
    );

}

 

export default Search;

Hope you can help me!!! Thanks in advance!

Agustin Moragues
  • 87
  • 1
  • 1
  • 8
  • is `CategoriasProvider` just `CategoriasContext.Provider` or is it a custom component? I think you've defined it without the right props (like `children`). Also the `CategoriasProvider` needs to be **outside** of the `App` component where you are using the `useContext` hook. – Linda Paiste Apr 18 '21 at 00:48
  • @LindaPaiste //interface export interface ICategoriasContextInterface { name: string | undefined; image: any | undefined; thumbnail:any; } export const CategoriasContext = react.createContext(null); export const CategoriasProvider= () => { const hola:ICategoriasContextInterface={name:'agustin',image:'someImage',thumbnail:'someThumbnail'}; return ( ... ); } export default CategoriasProvider; – Agustin Moragues Apr 18 '21 at 01:56
  • @LindaPaiste, sorry... Didn't styled as I expected, but yes, CategoriasProvider is just CategoriasContext.Provider. I also arranged CategoriasProvider outside App, but the error still appears. Hope you can help me :( – Agustin Moragues Apr 18 '21 at 01:59
  • Can you include `CategoriasProvider` code? – Luis Sardon Apr 18 '21 at 03:11
  • @LuisSardon sorry, I'll paste it here. You can later copy it in VSCode. – Agustin Moragues Apr 18 '21 at 03:15
  • @LuisSardon //interface export interface ICategoriasContextInterface { name: string | undefined; image: any | undefined; thumbnail:any; } export const CategoriasContext = react.createContext(null); export const CategoriasProvider= () => { const hola:ICategoriasContextInterface={name:'agustin',image:'someImage',thumbnail:'someThumbnail'}; return ( ... ); } export default CategoriasProvider; – Agustin Moragues Apr 18 '21 at 03:16
  • 1
    @LindaPaiste already mentioned the issue, you're missing some props on your CategoriesProvider function. – Luis Sardon Apr 18 '21 at 17:13

1 Answers1

16

The code which is causing the error in your title is in your comment. It's this line:

export const CategoriasProvider = () => {

You are defining CategoriasProvider as a component which takes no props. It can only accept IntrinsicAttributes which is basically just the key property.

But when you use CategoriasProvider in App you are calling it with JSX element children. You get an error because you have not said that the CategoriasProvider component can accept a children prop.

Any of the following types will solve your problem:

export const CategoriasProvider: React.FC = ({children}) => {
export const CategoriasProvider = ({children}: {children: React.ReactNode}) => {
export const CategoriasProvider = ({children}: React.PropsWithChildren<{}>) => {

Regardless, you'll want to pass the children down as children of the inner Provider component.

return (
  <CategoriasContext.Provider value={hola}>
    {children}
  </CategoriasContext.Provider>
);

Your App component is not going to work as expected because the useContext hook which accesses the CategoriasContext is located outside of the CategoriasProvider. It will just get the default value for the context -- not the value from the provider.

You need to rearrange your components such that the hook call occurs in a component that is rendered inside of the CategoriasProvider.

Try this:

const Search = () => {
  const contextValues = useContext(CategoriasContext);

  return (
    <div className="search">
      <Search
        name={contextValues?.name}
        image={contextValues?.image}
        thumbnail={contextValues?.thumbnail}
      />
    </div>
  );
};

const App = () => {
  return (
    <CategoriasProvider>
      <div className="App">
        <Search />
      </div>
    </CategoriasProvider>
  );
};

export default App;
Linda Paiste
  • 38,446
  • 6
  • 64
  • 102