lutaev
lutaev

Reputation: 337

New react native element is not accessible

I'm working on react-native project (main target is iPhone 6) and got some problems with including new elements in accessibility chain. For some reasons Voice Over does not update when new element appears after re-rendering. Hidden button does not appear in accessibility chain after running showButton() method. It becomes visible, but iOS Voice Over does not see it. The problem occurs only when app does something asynchronously. Here is my code:

export default class SmartView extends Component {
  constructor(props) {
    super(props)
    this.state = {
      showButton: false,
    }
  }

  showButton = () => {
    setTimeout(() => {
      this.setState({ showButton: true })
    }, 500)
  }

  render() {
    const { showButton } = this.state
    return (
      <View style={style.root}>
        <Button
          onPress={this.showButton}
          accessibilityRole="button"
          accessibilityTraits="button"
          accessibilityLabel="appeared"
          accessible
          simple
        >
          <Text>Appeared</Text>
        </Button>
        {showButton && (
          <Button
            accessibilityRole="button"
            accessibilityTraits="button"
            accessibilityLabel="appeared"
            accessible
            simple
          >
            <Text>Hidden</Text>
          </Button>
        )}
      </View>
    )
  }
}

So, if I remove setTimeout and do state updating in current js stream, everything work fine. Is there any possibility to make something like VoiceOverReload()?

I use: react-native v0.59.9 and iPhone 6, software version 12.4

Thanks.

Upvotes: 1

Views: 4105

Answers (2)

Medet Tleukabiluly
Medet Tleukabiluly

Reputation: 11940

Below demo works fine, probably your custom Button component has issues

import React, { useState } from 'react'
import { View, Text, TouchableOpacity } from 'react-native'

export default function Screen () {
  const [showButton, setShowButton] = useState(false)
  function handleShow () {
    setTimeout(() => {
      setShowButton(true)
    }, 1000)
  }
  return (
    <View style={{ padding: 40 }}>
      <TouchableOpacity
        onPress={handleShow}
        accessibilityRole='button'
        accessibilityTraits='button'
        accessibilityLabel='This button label is long for demo'
        accessible
        >
        <Text>Appeared</Text>
      </TouchableOpacity>
      {showButton && (
        <TouchableOpacity
          accessibilityRole='button'
          accessibilityTraits='button'
          accessibilityLabel='hidden'
          accessible
        >
          <Text>Hidden</Text>
        </TouchableOpacity>
      )}
    </View>
  )
}

Upvotes: 1

elyalvarado
elyalvarado

Reputation: 1296

If your view is going to update and you need voice over to detect the change faster, the you can add the following trait to the parent view: frequentUpdates. This will be the equivalent of setting "Updates Frequently" on the accessibility properties in XCode, as explained in the following answer: Making dynamically updating content in a UITableView accessible for VoiceOver

This works for ReactNative 0.59, though its deprecated and I don't know how to do it in newer versions of RN.

Upvotes: 0

Related Questions