Im building my first React-Native app With Meteor. I'm trying to fetch data from the database but I can't get it to work. I only have the handle with ready and stop properties but it doesn't contain any object data. Could someone explain how I can get the actual data from my database?
Container in the component:
export default createContainer(() => {
const handle = Meteor.subscribe('details-list');
return {
detailsReady: handle.ready(),
};
}, DetailsContainer);
Export in meteor app
export default () => {
Meteor.publish('details-list', () => {
return Details.find();
});
}
You need to add the data you want in the container, something like this:
export default createContainer(() => {
const handle = Meteor.subscribe('details-list');
return {
details: Details.find(),
detailsReady: handle.ready(),
};
}, DetailsContainer);
Related
In my project I'm using NextJs and tRPC for backend calls. I wanted to fetch some data in getServerSideProps using tRPC and provide it in Page component, also using react-query state for whole application. Here's my _app withTRPC config
export default withTRPC<AppRouter>({
config({ ctx }) {
const url = `${getBaseUrl()}/api/trpc`;
return {
url,
transformer: superjson,
queryClientConfig: { defaultOptions: { queries: { staleTime: 60 } } },
};
},
ssr: false,
})(MyApp);
I used ssr: false because of 'bug' in NextJs, which will cause to return empty props for first render, if set to true.
Here's my getServerSideProps function on the page
export const getServerSideProps = async () => {
const ssg = createSSGHelpers({
router: appRouter,
ctx: await createContext(),
transformer: superjson,
});
const entryRD = await getPageBySlug(option.some("trados"))();
await ssg.prefetchQuery("contentful.getProductList");
console.log("==>props", entryRD, ssg.dehydrate());
return {
props: {
trpcState: ssg.dehydrate(),
entryRD,
},
};
};
When I log to the console on server, both values are there, entryRD and ssg.dehydrate(). The latter contains object with mutations and queries and also data with correctly fetched data. Here is my page code:
const Page = ({ entryRD, trpcState }: InferGetServerSidePropsType<typeof getServerSideProps>) => {
const { data, isLoading } = trpc.useQuery(["contentful.getProductList"]);
console.log("==>data", data, isLoading);
return isLoading ? <div>Loading...</div> : <EntryCompontn entry={entryRD} />
When I read the docs, I understand it like:
fetch data on server,
use ssg.dehydrate() to return cache to component
when you use trpc.useQueried(), it will return cached value from state
Unfortunately data is empty and isLoading is true for a brief moment, when data is fetched. Did I misunderstood something, or did I make a mistake?
I am using firebase for my app and the data i read i want to put that in state to use it in different places.
it kinda works but when i want to console.log the state it updates like 30 times a second, am i doing something wrong?
this is my code
const db = firebase.firestore();
const [PBS1Detail, setPBS1Detail] = useState();
db.collection('Track').get().then((snapshot) => {
snapshot.docs.forEach(doc => {
renderTracks(doc)
}
)
});
const renderTracks = (doc) => {
let data = doc.data().data[0].Module;
return setPBS1Detail(data);
}
console.log(PBS1Detail)
i already tried to store it in a variable instead of state but thats not working for me, i can't get the variable from the function global
i am a noob i get it xd
You don't need a return statement when setting state. Also, it looks like you're performing some async function which means that when your component renders for the first time, PBS1Detail will be undefined since the db is a pending Promise.
You could/should put your async functions in useEffect hook:
useEffect(()=> {
db.collection('Track').get().then((snapshot) => {
snapshot.docs.forEach(doc => {
renderTracks(doc)
}
)
});
}, [])
const renderTracks = (doc) => {
let data = doc.data().data[0].Module;
setPBS1Detail(data);
}
Finally, your renderTracks function doesn't seem correct as it appears you're looping over docs and resetting your state each time.
Instead, maybe consider having an array for PBS1Detail
const [PBS1Detail, setPBS1Detail] = useState([]);
Then modify your async call:
useEffect(()=> {
db.collection('Track').get().then((snapshot) => {
let results = []
snapshot.docs.forEach(doc => {
results.push(renderTracks(doc))
}
)
setPBS1Detail(results)
});
}, [])
const renderTracks = (doc) => {
return doc.data().data[0].Module;
}
This way you're only setting state once and thus avoiding unnecessary re-renders and you're saving all of your docs instead of overwriting them.
being rather new to react.js + redux, I'm facing the following conundrum:
I have multiple files, which need to update the store in exactly the same way, based on the stores current state. Currently I simply copy-paste the same code (along with the needed mapStateToProps), which goes again DRY.
Similar to something like the below, where getData is an Ajax call living in the actions file and props.timeAttribute is coming from mapStateToProps:
props.getData(props.timeAttribute).then((newState) => {
console.log(newState)
})
Would a function like that go in the actions file? Can the current state be read from within that actions file? Or does one normally create some sort of helperFile.js in which a function like that lives and is being called from other files?
Thanks!
If your file is executing the same action, then yes, you would put the action creator in a separate file and export it. In theory, you can put state in an action by passing the state as a parameter, but the philosophy behind an action is that it announces to your application that SOMETHING HAPPENED (as denoted by the type property on the return value of the action function). The reducer function responsible for handling that type subsequently updates the state.
You can access the current state of the store inside of an action creator like this:
export const testAction = (someParam) => {
return (dispatch, getState) => {
const {
someState,
} = getState(); //getState gets the entire state of your application
//do something with someState and then run the dispatch function like this:
dispatch(() => {type: ACTION_TYPE, payload: updatedState})
}
I like this approach because it encapsulates all the logic for accessing state inside of the one function that will need to access it.
DO NOT modify the state inside of the action creator though! This should be read only. The state of your application should only be updated through your reducer functions.
Yes, it is recommended to maintain a separate file for your actions.
Below is an example of how i use an action to fetch information and dispatch an action.
export const fetchComments = () => (dispatch) => {
console.log("Fetch Comment invoked");
/*you can use your Ajax getData call instead of fetch.
Can also add parameters if you need */
return fetch(baseUrl + 'comments')
.then(response => {
if (response.ok){
return response;
}
else {
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
var errmess = new Error(error.message);
throw errmess;
})
.then(response => response.json())
.then(comments => dispatch(addComments(comments)))
.catch(error => dispatch(commentsFailed(error.message)));
}
/* Maintain a separate file called ActionTypes.js where you can store all the ActionTypes as Strings. */
export const addComments = (comments) => ({
type : ActionTypes.ADD_COMMENTS,
payload : comments
});
export const comments = (errMess) => ({
type : ActionTypes.COMMENTS_FAILED,
payload : errMess
});
Once, you receive dispatch an action, you need an reducer to capture the action and make changes to your store.
Note that this reducer must be a pure function.
export const comments = (state = { errMess: null, comments:[]}, action) => {
console.log("inside comments");
switch (action.type) {
case ActionTypes.ADD_COMMENTS:
return {...state, errMess: null, comments: action.payload};
case ActionTypes.COMMENTS_FAILED:
return {...state, errMess: action.payload};
default:
return state;
}
};
Don't forget to combine the reducers in the configureStore().
const store = createStore(
combineReducers({
comments
}),
applyMiddleware(thunk,logger)
);
In your components where you use the Actions, use
const mapDispatchToProps = dispatch => ({
fetchComments : () => dispatch(fetchComments()),
})
Note to export the component as
export default connect(mapStateToProps,mapDispatchToProps)(Component);
I want to get change layout according to wordpress page template (i get data with rest api)
API Data
{
"id": 47,
"template": "test.php", // need vue template according this
}
export default {
validate ({ params }) {
return !isNaN(+params.id)
},
async asyncData ({ params, error }) {
return fetch('http://wordpress.local/wp-json/wp/v2/'+params.postType+'/'+params.id)
.then(response => response.json())
.then(res => {
return { users: res }
})
},
layout () {
return 'blog' // Change here according to wordpress page template
},
}
I found a way to pass something from middleware to store which you can use inside the layout function. Here is the basic example I put together.
middleware/get-layout.js I simulate an async call here, could also be result of axios.post() for example
export default async (ctx) => {
return new Promise((resolve, reject) => {
// you can also access ctx.params here
ctx.store.commit('setLayout', 'new');
resolve();
});
}
store/index.js nothing crazy here
export const state = () => ({
layout: ''
})
export const mutations = {
setLayout(state, layout) {
state.layout = layout;
}
}
Middleware can either be registered globally for every route in nuxt.config.js or only for pages where you need this logic.
Finally using it in page component layout property:
layout(ctx) {
return ctx.store.state.layout;
}
I tested it with new.vue inside layout folder.
I am using Realm Database to store data for page navigation in my react native application.The below method stops working after I invoke realm.close()
Can you please suggest me what might be the issue.
export const getStorageProtags = () => {
return Realm.open({
schema: [ProtagsSchema]
}).then(realm => {
const protags = realm.objects('Protags');
realm.close();
return protags[0];
});
}