Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed child count (0) was not what we expected (1) #848

Closed
albullington opened this issue Nov 20, 2018 · 18 comments
Closed

Removed child count (0) was not what we expected (1) #848

albullington opened this issue Nov 20, 2018 · 18 comments
Labels
bug maybe fixed Missing repro This issue need minimum repro scenario

Comments

@albullington
Copy link

albullington commented Nov 20, 2018

I'm getting the following error on iOS only (specifically an iPhone SE running iOS 12) while rendering an area chart with a line and a gradient in React Native. I've been able to isolate the issue down to the <Line /> component which renders a <Path />, but I'm not sure how to stop the error from popping up each time I render the chart.

I also tested on Android, and there are no errors there.

img_1768

These are the versions I'm using:

"react-native": "0.57.1",
"react-native-svg": "^8.0.8",
"react-native-svg-charts": "^5.2.0",

And here is my code:

import React from "react";
import { View } from "react-native";
import {
  Defs,
  LinearGradient,
  Path,
  Stop
} from "react-native-svg";
import { AreaChart, XAxis, YAxis } from "react-native-svg-charts";
import * as scale from "d3-scale";
import * as shape from "d3-shape";
import moment from "moment";

const SpeciesChart = ( { data } ) => {
  const formatXAxis = ( index ) => {
    const allMonths = moment.monthsShort();
    if ( index === 0 || index % 2 === 0 ) {
      return "      " + allMonths[index];
    }
  };

  const Line = ( { line } ) => (
    <Path
      key="line"
      d={line}
      stroke="rgb(255, 255, 255)"
      strokeWidth="3"
      fill="none"
    />
  );

  const Gradient = ( { index } ) => (
    <Defs key={index}>
      <LinearGradient id="gradient" x1="0%" y="0%" x2="0%" y2="100%">
        <Stop offset="0%" stopColor="rgb(255, 255, 255)" stopOpacity={0.8} />
        <Stop offset="100%" stopColor="rgb(255, 255, 255)" stopOpacity={0.2} />
      </LinearGradient>
    </Defs>
  );

  return (
    <View>
      <YAxis
        data={data}
        yAccessor={ ( { item } ) => item.count }
        contentInset={styles.contentInset}
        svg={{ fontSize: 10, fill: "white" }}
        min={0}
        numberOfTicks={8}
      />
      <View style={styles.chartRow}>
        <AreaChart
          data={data}
          yAccessor={ ( { item } ) => item.count }
          xAccessor={( { item } ) => item.month }
          xScale={scale.scaleTime}
          yScale={scale.scaleLinear}
          contentInset={styles.contentInset}
          curve={shape.curveNatural}
          svg={{ fill: "url(#gradient)" }}
        >
          <Line />
          <Gradient />
        </AreaChart>
        <XAxis
          data={data}
          xAccessor={( { item } ) => item.month }
          formatLabel={ value => formatXAxis( value - 1 ) }
          svg={{
            fontSize: 10,
            fill: "white"
          }}
        />
      </View>
    </View>
  );
};

export default SpeciesChart;
@springroll12
Copy link

@albullington I am experiencing nearly the same issue. I also have an area graph with a line and a gradient, as well as some decorators. My areachart looks nearly identical to the one posted above.

I've noticed that the initial render of the areachart works, but when you try to redraw it with a different x/y axis (i.e. change the number of child elements to X/YAxis), that's when the crash occurs.

"react-native": "0.57.4",
"react-native-svg": "^8.0.8",
"react-native-svg-charts": "^5.2.0",

I have also tried react-native-svg, 7.0.3, 7.2.0 and 6.3.1. 6.3.1 does not experience this issue, but is buggy with newer react-natives (especially clips/gradients).

So far I've tried a few of the suggestions from similar issues with no success:

#789
(And the fix here: JesperLekland/react-native-svg-charts#238)

#258 (comment)

All of the suggestions seem to indicate that there should be only one sub-element of an SVG, especially if there is a Text element involved. However modifying the X/YAxis SVG with a G wrapper does not seem to work in my case.

@msand Let me know if there is anything I can do to help resolve this issue.

@ulvestad
Copy link

I am experiencing this as well. Using react-native-chart-kit and react-native-svg to render some linecharts. When I try to update data, this error occurs.

@niklassaers
Copy link

Any good advise on this? I'm struggling with the same and it's the one issue that is keeping me from releasing an updated app. Been sprinkling G's around so that Svg only contains one element, but still no luck. Been trying out latest of commit of react-native-svg-charts and react-native-svg together, but still no luck.

@albullington
Copy link
Author

I ended up using version of react-native-svg, 6.3.1, per @springroll12's suggestion. That stops the iOS app from crashing for me.

@ulvestad
Copy link

ulvestad commented Dec 8, 2018

Tried adding G's as well, and using the latest commit but nothing helped. Still confused

@msand
Copy link
Collaborator

msand commented Dec 9, 2018

Seems like a workaround is to wrap the second map over the children inside a G element: https://github.com/JesperLekland/react-native-svg-charts/blob/3309d13476707477d5c06ec8f0e50b6bfa4dc129/src/chart.js#L126-L133
Also, moving the Path element to the end of the Svg element removes the error: https://github.com/JesperLekland/react-native-svg-charts/blob/3309d13476707477d5c06ec8f0e50b6bfa4dc129/src/chart.js#L119-L125
Or, alternatively, removing the Gradient from the AreaChart.

import React, { Component } from 'react';
import {
  Text,
  View,
  TouchableWithoutFeedback,
  StyleSheet,
  Dimensions,
  Animated,
  Platform,
} from 'react-native';

import Svg, {
  Defs,
  LinearGradient,
  Stop,
  RadialGradient,
  G,
  Path,
  Circle,
  Rect,
  ClipPath,
  Symbol,
  Use,
  Image,
  Text as SvgText,
} from 'react-native-svg';

import { AreaChart, XAxis, YAxis } from 'react-native-svg-charts';
import * as scale from 'd3-scale';
import * as shape from 'd3-shape';
import moment from 'moment';

const contentInset = { top: 30, bottom: 30 };

const SpeciesChart = ({ data }) => {
  const formatXAxis = index => {
    const allMonths = moment.monthsShort();
    if (index === 0 || index % 2 === 0) {
      return '      ' + allMonths[index];
    }
  };

  const Line = ({ line }) => (
    <Path
      key="line"
      d={line}
      stroke="rgb(255, 255, 255)"
      strokeWidth="3"
      fill="none"
    />
  );

  const Gradient = ({ index }) => (
    <Defs key={index}>
      <LinearGradient id="gradient" x1="0%" y="0%" x2="0%" y2="100%">
        <Stop offset="0%" stopColor="rgb(255, 255, 255)" stopOpacity={0.8} />
        <Stop offset="100%" stopColor="rgb(255, 255, 255)" stopOpacity={0.2} />
      </LinearGradient>
    </Defs>
  );

  return (
    <View style={{ height: 200, padding: 20, flexDirection: 'row' }}>
      <YAxis
        data={data}
        yAccessor={({ item }) => item.count}
        contentInset={contentInset}
        svg={{ fontSize: 10, fill: 'white' }}
        min={0}
        numberOfTicks={8}
      />
      <View style={{ flex: 1 }}>
        <AreaChart
          data={data}
          yAccessor={({ item }) => item.count}
          xAccessor={({ item }) => item.month}
          xScale={scale.scaleTime}
          yScale={scale.scaleLinear}
          contentInset={contentInset}
          curve={shape.curveNatural}
          style={{ flex: 1 }}
          svg={{ fill: 'url(#gradient)' }}
        >
          <Line />
          <Gradient />
        </AreaChart>
        <XAxis
          data={data}
          xAccessor={({ item }) => item.month}
          formatLabel={value => formatXAxis(value - 1)}
          svg={{
            fontSize: 10,
            fill: 'white',
          }}
        />
      </View>
    </View>
  );
};

const data = [
  { month: 1, count: 3 },
  { month: 2, count: 4 },
  { month: 3, count: 5 },
  { month: 4, count: 3 },
  { month: 5, count: 4 },
  { month: 6, count: 5 },
  { month: 7, count: 3 },
  { month: 8, count: 4 },
  { month: 9, count: 5 },
  { month: 10, count: 3 },
  { month: 11, count: 4 },
  { month: 12, count: 5 },
];

export default class App extends Component {
  state = { scale: 1 };
  render() {
    const { scale } = this.state;
    return (
      <TouchableWithoutFeedback
        onPress={() => this.setState({ scale: scale === 1 ? 2 : 1 })}
      >
        <View style={styles.container}>
          <SpeciesChart
            data={data.map(d => ({ ...d, count: d.count * scale }))}
          />
        </View>
      </TouchableWithoutFeedback>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'black',
  },
});

@dreadjr
Copy link

dreadjr commented Dec 13, 2018

@msand I was able to get it work using
<Gradient index="somekey" />
or like you said, removing the gradient.

@springroll12
Copy link

@dreadjr Did you apply any of the other fixes @msand suggested (adding <G> wrappers to chart.js maps and/or moving the <Path> element to the end of the SVG) ?

@dreadjr
Copy link

dreadjr commented Dec 14, 2018

@springroll12 No, just ensuring the index property of the gradient was set.

@wmonecke
Copy link

Any updates on this?

@msand
Copy link
Collaborator

msand commented Jan 23, 2019

@wmonecke I would need more reproductions to analyze this further. Other than that it seems there exists workaround. So, seems relatively fine as no one else has provided broken examples yet.

@springroll12
Copy link

@msand I have not managed to succeed with any of the posted workarounds unfortunately.

The only change that made a difference so far was wrapping the second map in chart.js with <G>. This produced a different crash. I'll try to post an image of this shortly. Unfortunately I've not had a chance to work up a test case yet, but I will try in the near future.

@springroll12
Copy link

svg_chart_js_g_wrap_issue

This may not be helpful until you have a reproducible test case, but here is the error anyway. Here are my current package versions, however I've tried quite a few combinations at this point.

iOS 11.2
iPhone X simulator
react-native 0.57.6
react-native-svg 7.20
react-native-svg-charts 5.20

This error appears when I try to make the modifications suggested in the pull request here:

JesperLekland/react-native-svg-charts@e8b0baa

So far the bug in this thread and the crash shown in the screenshot above only occur on iOS for me. I'll try to work up a test case ASAP.

@bhavik13
Copy link

bhavik13 commented Feb 5, 2019

const Gradient = ({ index }) => ( <G> <Defs key={index}> <LinearGradient id="gradient" x1="0%" y="0%" x2="0%" y2="100%"> <Stop offset="0%" stopColor="rgb(255, 255, 255)" stopOpacity={0.8} /> <Stop offset="100%" stopColor="rgb(255, 255, 255)" stopOpacity={0.2} /> </LinearGradient> </Defs> </G> );

Add <G> tag

@msand
Copy link
Collaborator

msand commented Feb 9, 2019

I've traced this down to #755
If you want to use the latest code, and are willing to accept the tradeoff, you can use the fix_manage_children branch where I've reverted the cause of this, until a proper workaround can be found: facebook/react-native#23350

@msand
Copy link
Collaborator

msand commented Feb 9, 2019

Published v9.2.4 with a fix. Can you please test it?

@msand msand added maybe fixed Missing repro This issue need minimum repro scenario and removed help wanted labels Feb 9, 2019
@springroll12
Copy link

@msand This seems like it worked, but I'll have to test further to be sure.

Had a quick test of v9.2.4 and I can no longer reproduce either the original bug from this thread, or the secondary bug I posted earlier. Note that I've only tested on iOS with an iPhone X simulator so far:

iPhoneX simulator
react-native 0.57.7
react-native-svg 9.2.4
react-native-svg-charts 5.20

Note that this seems to work without applying any of the workarounds posted in this thread or elsewhere.

I'll have to give this a go on Android in the near future, but this looks like a good fix!

@springroll12
Copy link

Tested this on android today and all seems well. I think it's safe to say this is fixed!

Thanks @msand !

@msand msand closed this as completed Mar 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug maybe fixed Missing repro This issue need minimum repro scenario
Projects
None yet
Development

No branches or pull requests

8 participants