I am having an issue with recharts library, in this case BarChart component
What i want to achieve is to customize the label text in xAxis, i already created a custom component for tick, to make text too long having ellipsis or something like this, but seems i can't do anything for text overflow or decide any size.
Here's my code so far:
function renderTicks(props) {
console.log(props)
const space = props.width / props.visibleTicksCount
console.log(space)
const stringLength = props.payload.value.length * 7
console.log(stringLength)
return (
<text
style={{ fontSize: 10 }}
width={70} verticalAnchor="start" textAnchor="middle" x={props.x} y={props.y}>{props.payload.value}</text>
)
}
function BarChart({ config = {}, data = {} }) {
console.log(data)
return (
<StyledChart width={450} height={450} data={data} >
<XAxis
tick={renderTicks}
height={100}
interval={0} dataKey="name" >
<Label value="" content={<LabelCustom />} />
</XAxis>
<YAxis />
<Tooltip />
<Bar dataKey="value" fill={colorsChart[0]} />
</StyledChart>
);
}
Here is the current behaviour:
I found lot of problem like this browsering the problem but not valid solution,
any tip is appreciated
Related
In my application, I would like to have a StackBarChart component that clearly breaks down the data: https://recharts.org/en-US/examples/StackedBarChart and with any additional information in the tooltip as seen here: https://recharts.org/en-US/examples/CustomContentOfTooltip.
How can I add custom info in the tooltip and show the proper breakdown of data?
When I tried to incorporate code from Typescript Interface for Recharts Custom Tooltip, the only information that would show up in the tooltip would be the Text, not the breakdown of the data (aka A and B which are calls to an API). See code below:
const CustomTooltip = ({ active }: TooltipProps<ValueType, NameType>) => {
if( active ){
return (
<div className = "custom-tooltip">
<p className="Text"> Text: </p>
</div>
);
}
return null;
}
//more code
return (
<>
<Tooltip content = {<CustomTooltip />} labelStyle={{ color: "black" }} />
<Bar dataKey="other" />
<Bar dataKey="A" />
<Bar dataKey="B" />
);
See behavior in code sandbox: https://codesandbox.io/s/stacked-bar-chart-s47i2?file=/src/App.tsx
I have created a question array set dynamically in which it has multiple textinput fields and i want to change height of the text input when the content size increases.
const[height,setHeight]=useState(44)
But i have multiple text input with multiline option
<TextInput multiline height={height} placeholderText={'Question 1'}/>
<TextInput multiline height={height} placeholderText={'Question 2'}/>
<TextInput multiline height={height} placeholderText={'Question 3'}/>
<TextInput multiline height={height} placeholderText={'Question 4'}/>
<TextInput multiline height={height} placeholderText={'Question 5'}/>
<TextInput multiline height={height} placeholderText={'Question 6'}/>
These textinput fields are dynamically created based on array
I would write conditions that set the height based on the string length.
Like so :
Create a custom componentL
const CustomInput = ({question}) => {
const[height,setHeight]=useState(5)
const [response, setResponse] = useState(')
useEffect(() => {
if(response.length < 10) setHeight(5)
if(response.length > 10 && textHeight < 20) setHeight(10)
if(response.length > 20 && textHeight < 30) setHeight(30)
},[height])
return (<TextInput
multiline
onChange={(e) => setResponse(e)}
height={height}
placeholderText={'Question 1'}
/>)
}
And then in the parent component:
const arrayOfQuestion = ['Question1','Question2','Question3','Question4']
const ParentComponent = () => {
return (
<View style={yourStyle}>
{arrayOfQuestion.map((q, i) => {
return CustomInput key={i} question={q} />
})}
</View>
)
}
(Putting index as a key for a mapped element will work but is not a good practice. Find something unique instead, like a question id if your backend sends one)
Hi I am creating a barchart using the Recharts library. I am wanting to draw a trend line on top of the barchart like so:
I am using the following to draw the barchart:
<BarChart data={transformedDataByCategory}>
<CartesianGrid strokeDasharray="3 3" vertical={false} />
<XAxis
dataKey="category"
interval={0}
tickLine={false}
tick={(e) => {
const { payload: { value } } = e;
e.fill = theme.colors.onfCategory[value].base;
e.fontSize = '11px';
e.fontWeight = 'bold';
return <ChartText {...e}>{value}</ChartText>;
}}
/>
<YAxis />
<Legend />
<Tooltip cursor={{ fill: '#f1f1f1' }} />
{years.map((year, i) => <>
<Bar key={`year_${i}`} dataKey={year} fill={yearColours[i]}/>
</>)}
</BarChart>
I have tried using the ReferenceLine component to draw on top of the graph but have had no luck. Any help would be great thanks!
I have an icon position prop that decide whether it's placed on the left or on the right of the children. I have this working
<List>
{iconPosition === 'right' && (
<Text />
)}
{icon && (
<Icon />
)}
{iconPosition === 'left' && (
<Text />
)}
</List>
But I think it can be more simple, although in my opinion my above code is readable.
You can't do this any other way. You're using individual conditions with their own result.
Maybe you could place them on one line to make them more readable.
<List>
{iconPosition === 'right' && <Text />}
{icon && <Icon />}
{iconPosition === 'left' && <Text />}
</List>
or
render() {
const textLeft = (iconPosition === 'left');
const textRight = (iconPosition === 'right');
...
}
And use that. But that's mostly down to your preference / the coding style you and your colleagues are using..
One way to do it is to use css float (left/right) but it'll make the icon to be all the way to the right. Another way is to use flex box, take for example:
<div style="display: flex; flex-direction: row;">
<div style="flex: 0; order: 1;">(X)</div>
<div>content</div>
</div>
The (X) is the "icon". The order: 1; in the style moves it to the right, if you change it to 0 or ommit it, it'll be on the left.
so if you use this approach and put the text + icon in a flex row, all you need to do is:
<Icon style={{order: (iconPosition === 'right' ? 1 : 0)}} />
You could introduce a higher-order component to attempt to deal with it. It does add some complexity to the project though.
const WithConditionalRender = WrappedComponent => (
({ renderCondition, ...props }) => {
if (renderCondition) {
return <WrappedComponent { ...props } />;
}
return null;
}
);
const ConditionalText = WithConditionalRender(Text);
const ConditionalIcon = WithConditionalRender(Icon);
const Example = ({ icon, iconPosition }) => (
<List>
<ConditionalText renderCondition={ iconPosition === 'right' } />
<ConditionalIcon renderCondition={ icon } />
<ConditionalText renderCondition={ iconPosition === 'left' } />
</List>
);
This is a generic HOC and could be tweaked to be more specific.
I'm using React Native's Keyboard Avoiding View with the behavior set to padding (testing on Android).
I have multiple TextInputs on my screen. When I click the final TextInput, the keyboard covers it. I am now able to scroll down due to padding added from KeyboardAvoidingView, but it would be ideal to have it auto scroll on focus.
<Content>
<KeyboardAvoidingView behavior='padding'>
<TextInput placeholder='Example 1' />
<TextInput placeholder='Example 2' />
<TextInput placeholder='Example 3' />
<TextInput placeholder='Example 4' />
<TextInput placeholder='Example 5' />
<TextInput placeholder='Example 6' />
<TextInput placeholder='Example 7' />
</KeyboardAvoidingView>
</Content>
there is prop called keyboardVerticalOffset that you can pass to the KeyboardAvoidingView that will change how much the keyboard moves past the textInput.
Sample of my code:
const keyboardVerticalOffset = Platform.OS === 'ios' ? 40 : 0
return (
<KeyboardAvoidingView behavior='position' keyboardVerticalOffset={keyboardVerticalOffset}>
<ListView .../>
<KeyboardAvoidingView/>
)
Depending on platform, Android or IOS, implementation can be vary a little. This is how I did.
Add android:windowSoftInputMode="adjustResize" at AndroidManifest.xml,
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
</activity>
In your container
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : null}
keyboardVerticalOffset={Platform.OS === "ios" ? 64 : 0}>
<ScrollView>
{...}
</ScrollView>
</KeyboardAvoidingView>
keyboardVerticalOffset tells how much the keyboard moves past the textInput.
react-native-keyboard-aware-scroll-view
It's super simple to use and it worked great in both Android and iOS.
It supports older versions of RN too.
Initially I tried the KeyboardAvoidingView but on IOS not even
behavior='position' with keyboardVerticalOffset worked properly.
That used to overlap some content in a strange way.
I have:
RN 0.53.3
react-native-keyboard-aware-scroll-view 0.6.0
I added a few more details about my use case here:
https://stackoverflow.com/a/51151496/1979861
To add to #Maxwell's answer, sometimes you may need to scroll further than the end of the scroll view to get a component into view, since the added padding is not the full height of the keyboard. Full example below using scrollTo() with y offset as the height of the text input.
import React, { Component } from 'react'
import {
KeyboardAvoidingView,
ScrollView,
View,
TextInput
} from 'react-native'
export default class Test extends Component {
render() {
return (
<ScrollView style = {{flex:1, backgroundColor: 'white'}} ref = 'scroll'>
<KeyboardAvoidingView behavior='position' style = {{backgroundColor: 'white', flex: 1}}>
<View style = {{height: 400}}/>
<TextInput style = {{height: 60}} placeholder='Example 1' />
<TextInput style = {{height: 60}} placeholder='Example 2' />
<TextInput style = {{height: 60}} placeholder='Example 3' />
<TextInput style = {{height: 60}} placeholder='Example 4' onFocus = {() => this.refs['scroll'].scrollTo({y: 60})}/>
</KeyboardAvoidingView>
</ScrollView>
)
}
}
based on #Richard Millen something change in this styles
<ScrollView
contentContainerStyle={{
flexGrow: 1,
padding: 20
}}
>
<TextInput
style = {{ minHeight: 100 }}
/>
<TextInput
style = {{ minHeight: 100 }}
/>
...
</ScrollView>
if you are using react-navigation v6 you might need
import { useHeaderHeight } from "#react-navigation/elements";
const headerHeight = useHeaderHeight();
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : undefined}
style={flexGrow}
keyboardVerticalOffset={Platform.OS === "ios" ? headerHeight + Constants.statusBarHeight : 0}
>
</KeyboardAvoidingView>