首页 > 解决方案 > 在仅功能组件中设置 React Context

问题描述

我的目标很简单。我只是想从一个可重用的纯函数(无状态?)反应组件中设置我的反应上下文。

当这个可重用函数被调用时,它会将上下文(内部状态)设置为我提供的值。问题当然是您不能在仅功能组件中导入 react,因此我无法在整个应用程序中设置上下文。

没有什么可以真正表明它是一个简单的问题。

但以防万一:

<button onCLick={() => PlaySong()}></button>

export function PlaySong() {
  const {currentSong, setCurrentSong} = useContext(StoreContext) //cannot call useContext in this component
}

如果我使用常规的反应组件,我不能在点击时调用这个函数:

export default function PlaySong() {
  const {currentSong, setCurrentSong} = useContext(StoreContext) //fine
}

但:

<button onCLick={() => <PlaySong />}></button> //not an executable function

一个解决方案:我知道我可以通过简单地创建一个 Playbtn 组件并将其放置在每首歌曲中以便它播放歌曲来轻松解决这个问题。这种方法的问题是我正在使用一个 react-player 库,所以我不能在其中放置一个 Playbtn 组件......

标签: reactjsreact-componentreact-context

解决方案


你这么近!您只需要在函数组件内定义回调。

export const PlaySongButton = ({...props}) => {
  
  const {setCurrentSong} = useContext(StoreContext);

  const playSong = () => {
    setCurrentSong("some song");
  }

  return (
    <button 
      {...props}
      onClick={() => playSong()}
    />
  )
}

如果您想要更高的可重用性,您可以创建自定义挂钩来使用您的上下文。当然你在哪里使用这些还是要遵守hooks 的规则

export const useSetCurrentSong = (song) => {
  const {setCurrentSong} = useContext(StoreContext);
  setCurrentSong(song);
}

可以通过渲染一个组件来触发一个钩子函数,但是你不能像你试图做的那样调用一个组件。

const PlaySong = () => {
  const {setCurrentSong} = useContext(StoreContext);
  useEffect( () => { 
     setCurrentSong("some song");
    }, []
  }
  return null;
}
const MyComponent = () => {
   const [shouldPlay, setShouldPlay] = useState(false);
   
   return (
     <>
       <button onClick={() => setShouldPlay(true)}>Play</button>
       {shouldPlay && <PlaySong />}
     </>
   ) 
}

推荐阅读