A modular React Native widget for feedback and satisfaction surveys, developed by SoluCX following Clean Code principles and scalable architecture.
The SoluCX Widget allows you to integrate satisfaction surveys directly into React Native/Expo applications simply and flexibly. Designed for companies that need to collect real-time feedback through different presentation modes.
4 Rendering Modes : Bottom, Top, Modal, and InlineAutomatic Persistence : Smart frequency controlWebView Communication : Seamless integration with SoluCX platformTypeScript : Fully typed for better developer experienceHigh Performance : Optimized loading and local cache Expo Managed Workflow Bare React Native
npx expo install @solucx/react-native-solucx-widget
pnpm dlx expo install @solucx/react-native-solucx-widget
bun x expo install @solucx/react-native-solucx-widget
yarn dlx expo install @solucx/react-native-solucx-widget
npm i @solucx/react-native-solucx-widget react-native-webview @react-native-async-storage/async-storage react-native-reanimated react-native-worklets
pnpm i @solucx/react-native-solucx-widget react-native-webview @react-native-async-storage/async-storage react-native-reanimated react-native-worklets
bun add @solucx/react-native-solucx-widget react-native-webview @react-native-async-storage/async-storage react-native-reanimated react-native-worklets
yarn add @solucx/react-native-solucx-widget react-native-webview @react-native-async-storage/async-storage react-native-reanimated react-native-worklets
babel.config.js
module . exports = {
presets: [
... // don't add it here :)
],
plugins: [
...
'react-native-worklets/plugin' ,
],
};
In React Native without Expo (Bare React Native) projects, you must manually install native modules after package installation. In Expo Managed Workflow projects, native module installation is handled automatically.
app.tsx
import { SoluCXWidget } from '@solucx/react-native-solucx-widget' ;
import { StyleSheet, Text, View } from 'react-native' ;
export default function App () {
return (
< View style = {styles.container} >
< Text >Open up App.js to start working on your app !</ Text >
< SoluCXWidget
soluCXKey = ""
type = "inline"
data = {{
journey : "" ,
name : "Cliente" ,
email : '[email protected] ' ,
store_id : '1' ,
employee_id : '1' ,
amount : 10 ,
param_REGIAO : 'SUDESTE'
}}
options = {{}}
/>
</ View >
);
}
package.json
{
"dependencies" : {
"@solucx/react-native-solucx-widget" : "^0.1.5"
}
}
Widget fixed at the bottom of the screen, ideal for non-intrusive feedback.
< SoluCXWidget type = "bottom" { ... props} />
Widget fixed at the top of the screen, perfect for important notifications.
< SoluCXWidget type = "top" { ... props} />
Centered overlay that blocks interaction with the background.
< SoluCXWidget type = "modal" { ... props} />
Integrated into the normal layout flow, respecting its position in the code.
< SoluCXWidget type = "inline" { ... props} />
Property Type Required Description soluCXKeystring✅ SoluCX authentication key typeWidgetType✅ Rendering mode dataWidgetData✅ Customer/transaction data optionsWidgetOptions✅ Widget settings callbacksWidgetCallbacks❌ Callbacks for journey tracking
interface WidgetData {
// Identifiers
transaction_id ?: string ;
customer_id ?: string ;
// Customer data
name ?: string ;
email ?: string ;
phone ?: string ;
birth_date ?: string ; // Format: YYYY-MM-DD
document ?: string ;
// Transaction context
store_id ?: string ;
store_name ?: string ;
employee_id ?: string ;
employee_name ?: string ;
amount ?: number ;
score ?: number ;
journey ?: string ; // Journey/flow name
// Custom parameters (prefix param_)
param_REGION ?: string ;
[ key : string ] : string | number | undefined ;
}
interface WidgetOptions {
height ?: number ; // Height
retry ?: {
attempts ?: number ; // Attempts (default: 3)
interval ?: number ; // Interval in ms (default: 1000)
};
waitDelayAfterRating ?: number ; // Delay after rating
}
type WidgetType = "bottom" | "top" | "inline" | "modal" ;
interface WidgetCallbacks {
onOpened ?: ( userId : string ) => void ;
onClosed ?: () => void ;
onError ?: ( message : string ) => void ;
onPageChanged ?: ( page : string ) => void ;
onQuestionAnswered ?: () => void ;
onCompleted ?: ( userId : string ) => void ;
onPartialCompleted ?: ( userId : string ) => void ;
onResize ?: ( height : string ) => void ;
}
Callback Parameter Description onOpeneduserId: stringCalled when the widget is opened onClosed- Called when the widget is closed onErrormessage: stringCalled when a loading error occurs onPageChangedpage: stringCalled when the user navigates between survey pages onQuestionAnswered- Called when the user answers a question onCompleteduserId: stringCalled when the survey is completed onPartialCompleteduserId: stringCalled when the survey is partially completed onResizeheight: stringCalled when the widget is resized
import { SoluCXWidget } from '@solucx/react-native-solucx-widget' ;
export default function App () {
return (
< SoluCXWidget
soluCXKey = "YOUR_KEY"
type = "modal"
data = {{
journey : "purchase" ,
name : "Customer" ,
email : "[email protected] " ,
store_id : "1" ,
}}
options = {{}}
callbacks = {{
onOpened : ( userId ) => {
console. log ( 'Widget opened for:' , userId);
},
onCompleted : ( userId ) => {
console. log ( 'Survey completed by:' , userId);
},
onPageChanged : ( page ) => {
console. log ( 'Page changed:' , page);
},
onQuestionAnswered : () => {
console. log ( 'Question answered' );
},
onClosed : () => {
console. log ( 'Widget closed' );
},
onError : ( message ) => {
console. error ( 'Widget error:' , message);
},
}}
/>
);
}
The widget automatically processes the following survey events:
FORM_OPENED - Widget openedFORM_CLOSE - User closed the widgetFORM_COMPLETED - Survey completedFORM_PARTIALCOMPLETED - Partially completedFORM_RESIZE - Widget resizedFORM_ERROR - Loading errorFORM_PAGECHANGED - Survey page changedQUESTION_ANSWERED - Question answeredThe events above are processed internally by the widget. To receive these events in your app, use the callbacks prop described above.
The widget automatically controls:
Attempt history : Prevents widget spamLast rating : Date of last interactionFrequency control : Respects display settingsLocal storage : Data persists between sessions
const widgets = [ 'bottom' , 'top' ] as WidgetType [];
return (
<>
{ widgets . map (( type ) => (
< SoluCXWidget
key = {type}
soluCXKey = {key}
type = {type}
data = {data}
options = {options}
/>
))}
</>
);
⚠️ Critical Behavior : The position in JSX does not determine where top, bottom, and modal widgets appear:
// ❌ "bottom" widget always appears at the bottom, regardless of position
< Text >Content before </ Text >
< SoluCXWidget type = "bottom" { ... props} />
< Text >Content after </ Text >
// ✅ Only "inline" respects its position in the code
< Text >Content before </ Text >
< SoluCXWidget type = "inline" { ... props} />
< Text >Content after </ Text >
// Essential checks:
// ✅ Valid SoluCX key?
// ✅ Internet connectivity?
// ✅ WebView logs in console?
// ✅ Required data filled?
// Communication debug:
const handleMessage = ( message : string ) => {
console. log ( 'Widget event:' , message);
};
// Check if JavaScript was injected correctly
// Adjust dimensions for the device:
const { height } = Dimensions. get ( 'window' );
const options = {
height: Math. min (height * 0.6 , 400 )
};
Version React Native Expo iOS Android 1.0.x 0.70+ 50+ 11+ API 21+
This package is proprietary to SoluCX. Use is restricted to licensed SoluCX platform customers.