Im setting my store on my react native app, is working fine with redux-dev-tools,
but I dont know how to refactor.
const store = createStore(reducer, /* preloadedState, */
composeEnhancers(
applyMiddleware(...middleware)));
const configureStore = () => {
return store;
};
export { configureStore };
The goal is to export only "store" as a function
Why do you want to export store as a function as you could just as well export it as an object?
export const store = configureStore();
This way you could also just import it in any file you like:
import { store } from '...';
// Now you can access the redux store and dispatch actions:
store.getState() ...
store.dispatch(...)
Related
I am trying out a small sample in nextjs. All that the proj does is to fetch json data from a file and try displaying it in list of a component. But the behavior is weird. Its getting into infinite loop and I have no clue what's wrong. Could some one take a look at https://github.com/SamplesForMurthy/sampleCode and help me figure out what the issue is? Not able to fetch the data nor I am able to display.
I cloned and fixed. You don't need to use fs.readFileSync here, or fs at all for that matter. You can simply import the .json file as an arbitrarily named variable then map it out.
Here is how I got the data rendering:
import React from 'react';
import testData from '../TestData/SampleData.json';
import SampleParentComponent from '../components/SampleParentComponent';
function TestPage({ filecontent }) {
console.log(`filecontent: ${filecontent}`);
return (
<div>
<SampleParentComponent data={filecontent}></SampleParentComponent>
</div>
);
}
export const getStaticProps = async ctx => {
console.log(ctx.query);
const filecontent = await testData;
return {
props: { filecontent }
};
};
export default TestPage;
/**
* (property) filecontent: {
data: {
seqNo: number;
contactName: string;
}[];
}
*/
I want to change all the static text in my app with a text from a server so I have to fetch this text in LoadingScreen and then export it to use it in other screens
<Text>My products</Text> to <Text>{constants.myProduct}</Text> after import constant from LoadingScreen
How to export the json response from LoadingScreen to all the other Screen ?
there is another approach ?
PS. I don't use Redux
The simplest way, but not the best, is just create and export variable with all text keys. For example:
// text.utils.js
let _textData;
export const loadTextData = () => fetch(YOUR_SERVER)
.then((r) => r.json())
.then(r => _textData = r);
export const getTextData = (key, defaultValue) => _textData[key] || defaultValue;
// init inside App or something else
import {loadTextData} from 'text.utils.js';
componentDidMount() {
loadTextData();
}
// inside components
import {getTextData} from 'text.utils.js';
const myProductText = getTextData('myProduct', 'This is product text');
const myProductCountText = getTextData('myProductCount', 'This is product count text');
<Text>{myProductText}</Text>
<Text>{myProductCountText}</Text>
P.S. It's not a good solution for react. The best choice is create a context or hook, that will provide strings to your components. Also if your string object has nested objects, you may reorganise getTextData function
I'm trying to have my add data from a local static JSON file to the Vue vuex store.
I want my JSON file separated from the bundle process, so that i can change the content anytime in future, without rebuilding the whole site.
I have my json file [test.json] in the public folder
And with the following code, i managed to import the data, but its still being bundled on build of the site.
import data from '../public/test';
export const state = () => ({
allData: {}
})
export const mutations = {
SET_ALL_DATA(state, data) {
state.allData = data
}
}
export const actions = {
nuxtServerInit({ commit }) {
commit('SET_ALL_DATA', data)
}
}
I have also tried hosting the JSON file on a web server and doing an axios call to it on nuxtServerInit like so. but the called upon json file still gets bundled, as changing the hosted json file does nothing to update the content.
export const actions = {
async nuxtServerInit ({ commit }, { $axios }) {
const res = await $axios.$get('https://www.amq.fariskassim.com/testjson/test.json')
commit('SET_ALL_DATA', res)
}
}
I'm all out of solutions so if anyone can point me in the right direction, i would be totally grateful
I am trying to import a CSV for use with the D3 library to create a chart within a Create React App project, but importing the file is throwing a "Cannot find module" error even though the path to the CSV file is correct.
I have a feeling this might be something to do with CRA's Webpack config under the hood but it looks like this is using the file loader so I'm not sure what the issue is. The data file is within CRA's src directory.
The console log in the code below is running with the correct data in, which means the data must be being accessed. The error is thrown after this (Although the path to the CSV is underlined red in my editor).
I am using TypeScript but I don't think this has anything to do with the problem.
import React from 'react';
import * as d3 from 'd3';
import CSVData from '../data/data.csv';
const BarChart: React.FC = () => {
d3.csv(CSVData).then(res => {
console.log(res);
});
return <div>Test</div>;
};
export default BarChart;
CRA doesn't support importing .csv files. Without ejecting from CRA, your best option is to copy that file along with the results of yarn/npm build to your web server and then fetching it at runtime.
If that CSV is big (more than a few kb), then it is also the better option in terms of performance/code splitting.
Thanks to Nick Ribal for his answer, I found a similar solution by moving my data file into the public folder and then referencing this via the PUBLIC_URL environment variable.
I used the D3 CSV method which will get data from a URL if passed one rather than using fetch and parsing this as text.
With D3 CSV method:
import React, { useState } from 'react';
import { DSVRowArray } from 'd3';
import * as d3 from 'd3';
type CSVData = DSVRowArray | null;
const BarChart: React.FC = () => {
const initialState: CSVData = null;
const [fetchedCSVData, setFetchedCSVdata] = useState<CSVData>(initialState);
if (!fetchedCSVData) {
d3.csv(`${process.env.PUBLIC_URL}/data/data.csv`).then(res => {
setFetchedCSVdata(res);
});
}
return <div>Test</div>;
};
export default BarChart;
Without D3 CSV method:
import React, { useState } from 'react';
type CSVData = string | null;
const BarChart: React.FC = () => {
const initialState: CSVData = null;
const [fetchedCSVData, setFetchedCSVData] = useState<CSVData>(initialState);
if (!fetchedCSVData) {
fetch(`${process.env.PUBLIC_URL}/data/data.csv`)
.then(res => res.text())
.then(stringData => {
console.log(stringData);
setFetchedCSVData(stringData);
});
}
return <div>Test</div>;
};
export default BarChart;
I am creating a Spotify app with its API. I want 4 views (like '/', 'nowPlaying', 'favouriteArtists', 'favouriteSongs').
I need to setAccessToken for using functions like getMyCurrentPlaybackState() in every new page, right?. Idk if I need to if(params.access_token){spotifyWebApi.setAccessToken(params.access_token)} in every container that will use functions like getMyCurrentPlaybackState(). I was thinking of creating a Spotify.jsx container that handle the store of the Spotify Object (which is used in the token and in every container that use spotify functions). But with this Spotify.jsx i don't know either if it is a good approach nor how to connect its needed spotifyWebApi const to every container file and token file.
For better understanding of my idea: I would create a Token.jsx that has getHashParams() and a Playing.jsx that has getNowPlaying(). Every one needs the spotifyWebApi const.
import React, { Component } from 'react';
import Spotify from 'spotify-web-api-js';
const spotifyWebApi = new Spotify();
class App extends Component {
constructor(){
super();
const params = this.getHashParams();
this.state = {
loggedIn: params.access_token ? true : false,
nowPlaying: {
name: 'Not Checked',
image: ''
}
}
if (params.access_token){
spotifyWebApi.setAccessToken(params.access_token)
}
}
getHashParams() {
var hashParams = {};
var e, r = /([^&;=]+)=?([^&;]*)/g,
q = window.location.hash.substring(1);
while ( e = r.exec(q)) {
hashParams[e[1]] = decodeURIComponent(e[2]);
}
return hashParams;
}
getNowPlaying(){
spotifyWebApi.getMyCurrentPlaybackState()
.then((response) => {
this.setState({
nowPlaying: {
name: response.item.name,
image: response.item.album.images[0].url
}
})
})
}
}
Your title mentions Redux, but I don't see your code utilizing it. With Redux, you could get the access_token and then store it in state. This will allow you to use it in any Redux connected component.
Also, with Redux, you can use Redux Thunk (or similar) middleware that will allow you to use Redux actions to call an API. So then you would just write the different API calls as Redux actions, which would allow you to call them from any component, and have the results added to your Redux store (which again, can be used in any Redux connected component).
So, for example, your getNowPlaying() function could be an action looking something like this:
function getNowPlaying() {
return function (dispatch, getState) {
// get the token and init the api
const access_token = getState().spotify.access_token
spotifyWebApi.setAccessToken(access_token)
return spotifyWebApi.getMyCurrentPlaybackState().then((response) => {
dispatch({
type: 'SET_NOW_PLAYING',
name: response.item.name,
image: response.item.album.images[0].url
})
})
}
}
Note: You'll need to configure the Redux reducer for "spotify" (or however you want to structure your store) to store the data you need.
So, you could then call getNowPlaying() from any component. It stores the results in the redux store, which you could also use from any connected component. And you can use the same technique of getting the access_token from the store when needed in the actions.
Alternatively, if you didn't want to use Redux, you could provide context values to all child components, using React's Context features. You could do this with that token that each component would need in your setup. But Redux, in my opinion, is the better option for you here.
Instead of passing this const to other components, I would create a SpotifyUtils.jsx and inside it declare the const. And in this helper file I would export functions so other components can use them.
For example:
import Spotify from 'spotify-web-api-js';
const spotifyWebApi = new Spotify();
let token = null
export function isLoggedIn() {
return !!token
}
export function setAccessToke(_token) {
token = _token;
spotifyWebApi.setAccessToken(_token);
}
export function getNowPlaying(){
return spotifyWebApi.getMyCurrentPlaybackState()
.then((response) => {
return {
name: response.item.name,
image: response.item.album.images[0].url
}
})
}
So that in the components you can use them like so:
import React, { Component } from 'react';
import {
isLoggedIn,
setAccessToken,
getNowPlaying,
} from 'helpers/SpotifyUtils'
class App extends Component {
constructor(){
super();
this.state = {
loggedIn: isLoggedIn(),
nowPlaying: {
name: 'Not Checked',
image: ''
}
}
getHashParams() {
var hashParams = {};
var e, r = /([^&;=]+)=?([^&;]*)/g,
q = window.location.hash.substring(1);
while ( e = r.exec(q)) {
hashParams[e[1]] = decodeURIComponent(e[2]);
}
return hashParams;
}
componentDidMount() {
if (!this.state.loggedIn) {
const params = this.getHashParams();
if (params.access_token) {
setAccessToken(params.access_token)
getNowPlaying()
.then(nowPlaying => this.setState({ nowPlaying }))
}
}
}
}
This will enable your spotifyWebApi const to be reused in any component you import the helper functions. I am particularly found of this pattern, creating utils or helpers in a generic fashion so that you can reuse code easily. Also if spotify Web Api releases a breaking change, your refactor will be easier because you will only need to refactor the SpotifyUtils.jsx file since it will be the only file using import Spotify from 'spotify-web-api-js'