morganney / tts-react

Convert text to speech using React.
https://morganney.github.io/tts-react/
MIT License
50 stars 7 forks source link

Why text inside component is not getting read ? #39

Closed KesavarajaRK closed 1 year ago

KesavarajaRK commented 1 year ago

Thanks for the awesome package. I wanted to know the reason the text inside a component is not getting read by the package or I am doing wrong. Sample is here https://codesandbox.io/s/eloquent-newton-7l2re2?file=/src/App.js. image

Kindly guide me.

morganney commented 1 year ago

Hi there.

Let me first address some trivial issues with your code on CodeSandbox. Which, by the way, I do not recommend using Codesandbox to experiment with the Web Speech API. It exhibits wonky behavior, either due to it's usage of iframes or something else. You should be testing your code in a local development environment.

To address the more significant issue of why the last <a> text is not being spoken, that is because tts-react is using Children.map recursively to find the necessary text to pass to a SpeechSynthesisUtterance, and currently if you check the caveats it states:

The traversal does not go deeper than React elements: they don’t get rendered, and their children aren’t traversed.

Thus, when you encode the last <a> tag as a React functional component in your CodeSandbox example, there is no way for tts-react to determine the children of <ContentComponent /> using supported React API's. I should update the documentation to specifically call out this issue.

In order to get the text from the last <a> tag spoken, the one rendered inside <ContentComponent />, you would have to include it as direct HTML children inside <TextToSpeech>. Here is an updated CodeSandbox example.

I do not think I want to attempt to use some other React API in an unsupported way to attempt to add support for nested React children inside <TextToSpeech>, at least not until I lock support down to a specific React version >= 18 (but you're welcome to open a PR). Currently, tts-react supports React 17 and 18 which have different API's for rendering. As time permits, I have been working on a custom HTML element tts-element (WIP) that uses native DOM API's to mimic the behavior of tts-react. In my opinion, that will provide a more robust solution to speaking/highlighting text within the DOM using the Web Speech API.

At the current time, the solution is to not nest React components inside <TextToSpeech>. I will update the README and other documentation to specifically call this out.